mirror of
https://github.com/standardnotes/server
synced 2026-05-12 06:57:20 -04:00
Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ae1e86e19f | |||
| 9f76e389e2 | |||
| 6e2240e60c | |||
| cd37c951bb | |||
| c4c3dfb823 | |||
| c4b6f17ebc | |||
| 71ce938cb1 | |||
| dc76113915 | |||
| 6583ff6cd9 | |||
| 69ea947857 | |||
| eab78b3a95 | |||
| 3097f7f063 | |||
| 126989df82 | |||
| a25eb178c5 | |||
| 18dae26b8e | |||
| 5bc8157d4d | |||
| f29826e917 | |||
| ba7cbb989b | |||
| d4579ce21e | |||
| ed14d2dfb7 | |||
| 64f1fe59c2 | |||
| 207ef9f3e5 | |||
| 3ea0435459 | |||
| 7668713dd6 | |||
| f6bc1c3084 | |||
| 4203ff9a0c | |||
| 0281724196 | |||
| 94bd319279 | |||
| 373cfad1f7 | |||
| 59107f8553 | |||
| e066b6a126 | |||
| a0e4926135 | |||
| b1b244a2cf | |||
| b4a38d9dcc | |||
| 71e2a4187e | |||
| c94f9c1a60 | |||
| b9907924be | |||
| d4c188c096 | |||
| 2ccaf490df | |||
| cd893b41d7 | |||
| 3838358081 | |||
| 1a388f00c3 | |||
| bd71422fab | |||
| 3e1697f47f | |||
| 032cde7723 | |||
| 34b956b482 | |||
| 681e0378ae | |||
| 609e85f926 | |||
| e4ca310707 | |||
| d606493356 | |||
| 5ef6c5c14a | |||
| 0188f290f9 | |||
| 676cf36f8d | |||
| f8aef6c8ef | |||
| 5bf8cf49c1 | |||
| 51cd0a4dad | |||
| 1d06ffe9d5 |
@@ -38,6 +38,10 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
jq '(.containerDefinitions[] | select(.name=="${{ inputs.service_name }}-prod") | .environment[] | select(.name=="VERSION")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
jq '(.containerDefinitions[] | select(.name=="${{ inputs.service_name }}-prod") | .environment[] | select(.name=="VERSION")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
||||||
|
|
||||||
|
- name: Fill in the new package version in the Amazon ECS task definition
|
||||||
|
run: |
|
||||||
|
jq '(.containerDefinitions[] | select(.name=="${{ inputs.service_name }}-prod") | .environment[] | select(.name=="npm_package_version")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
||||||
|
|
||||||
- name: Fill in the new image ID in the Amazon ECS task definition
|
- name: Fill in the new image ID in the Amazon ECS task definition
|
||||||
id: task-def-prod
|
id: task-def-prod
|
||||||
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ on:
|
|||||||
type: string
|
type: string
|
||||||
default: latest
|
default: latest
|
||||||
description: The Docker image tag used for SNJS container
|
description: The Docker image tag used for SNJS container
|
||||||
|
suite:
|
||||||
|
type: string
|
||||||
|
default: all
|
||||||
|
description: The test suite to run
|
||||||
secrets:
|
secrets:
|
||||||
DOCKER_USERNAME:
|
DOCKER_USERNAME:
|
||||||
required: true
|
required: true
|
||||||
@@ -18,149 +22,16 @@ on:
|
|||||||
required: true
|
required: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
e2e:
|
e2e-self-hosted:
|
||||||
name: (Self Hosting) E2E Test Suite
|
uses: standardnotes/server/.github/workflows/e2e-self-hosted.yml@main
|
||||||
strategy:
|
with:
|
||||||
fail-fast: false
|
snjs_image_tag: ${{ inputs.snjs_image_tag }}
|
||||||
matrix:
|
suite: ${{ inputs.suite }}
|
||||||
secondary_db_enabled: [true, false]
|
secrets: inherit
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
services:
|
|
||||||
snjs:
|
|
||||||
image: standardnotes/snjs:${{ inputs.snjs_image_tag }}
|
|
||||||
ports:
|
|
||||||
- 9001:9001
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Set up Node
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
registry-url: 'https://registry.npmjs.org'
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
|
|
||||||
- name: Install
|
|
||||||
run: yarn install --immutable
|
|
||||||
|
|
||||||
- name: Run Server
|
|
||||||
run: docker compose -f docker-compose.ci.yml up -d
|
|
||||||
env:
|
|
||||||
DB_TYPE: mysql
|
|
||||||
CACHE_TYPE: redis
|
|
||||||
SECONDARY_DB_ENABLED: ${{ matrix.secondary_db_enabled }}
|
|
||||||
|
|
||||||
- name: Wait for server to start
|
|
||||||
run: docker/is-available.sh http://localhost:3123 $(pwd)/logs
|
|
||||||
|
|
||||||
- name: Run E2E Test Suite
|
|
||||||
run: yarn dlx mocha-headless-chrome --timeout 3600000 -f http://localhost:9001/mocha/test.html
|
|
||||||
|
|
||||||
- name: Show logs on failure
|
|
||||||
if: ${{ failure() }}
|
|
||||||
run: |
|
|
||||||
echo "# Errors:"
|
|
||||||
tail -n 100 logs/*.err
|
|
||||||
echo "# Logs:"
|
|
||||||
tail -n 100 logs/*.log
|
|
||||||
|
|
||||||
e2e-home-server:
|
e2e-home-server:
|
||||||
name: (Home Server) E2E Test Suite
|
uses: standardnotes/server/.github/workflows/e2e-home-server.yml@main
|
||||||
strategy:
|
with:
|
||||||
fail-fast: false
|
snjs_image_tag: ${{ inputs.snjs_image_tag }}
|
||||||
matrix:
|
suite: ${{ inputs.suite }}
|
||||||
db_type: [mysql, sqlite]
|
secrets: inherit
|
||||||
cache_type: [redis, memory]
|
|
||||||
secondary_db_enabled: [true, false]
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
services:
|
|
||||||
snjs:
|
|
||||||
image: standardnotes/snjs:${{ inputs.snjs_image_tag }}
|
|
||||||
ports:
|
|
||||||
- 9001:9001
|
|
||||||
cache:
|
|
||||||
image: redis
|
|
||||||
ports:
|
|
||||||
- 6379:6379
|
|
||||||
db:
|
|
||||||
image: mysql
|
|
||||||
ports:
|
|
||||||
- 3306:3306
|
|
||||||
env:
|
|
||||||
MYSQL_ROOT_PASSWORD: root
|
|
||||||
MYSQL_DATABASE: standardnotes
|
|
||||||
MYSQL_USER: standardnotes
|
|
||||||
MYSQL_PASSWORD: standardnotes
|
|
||||||
secondary_db:
|
|
||||||
image: mongo:5.0
|
|
||||||
ports:
|
|
||||||
- 27017:27017
|
|
||||||
env:
|
|
||||||
MONGO_INITDB_ROOT_USERNAME: standardnotes
|
|
||||||
MONGO_INITDB_ROOT_PASSWORD: standardnotes
|
|
||||||
MONGO_INITDB_DATABASE: standardnotes
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Set up Node
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
registry-url: 'https://registry.npmjs.org'
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
|
|
||||||
- name: Install Dependencies
|
|
||||||
run: yarn install --immutable
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: yarn build
|
|
||||||
|
|
||||||
- name: Copy dotenv file
|
|
||||||
run: cp packages/home-server/.env.sample packages/home-server/.env
|
|
||||||
|
|
||||||
- name: Fill in env variables
|
|
||||||
run: |
|
|
||||||
sed -i "s/JWT_SECRET=/JWT_SECRET=$(openssl rand -hex 32)/g" packages/home-server/.env
|
|
||||||
sed -i "s/AUTH_JWT_SECRET=/AUTH_JWT_SECRET=$(openssl rand -hex 32)/g" packages/home-server/.env
|
|
||||||
sed -i "s/ENCRYPTION_SERVER_KEY=/ENCRYPTION_SERVER_KEY=$(openssl rand -hex 32)/g" packages/home-server/.env
|
|
||||||
sed -i "s/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=10" >> packages/home-server/.env
|
|
||||||
echo "REVISIONS_FREQUENCY=2" >> packages/home-server/.env
|
|
||||||
echo "DB_HOST=localhost" >> packages/home-server/.env
|
|
||||||
echo "DB_PORT=3306" >> packages/home-server/.env
|
|
||||||
echo "DB_DATABASE=standardnotes" >> packages/home-server/.env
|
|
||||||
echo "DB_SQLITE_DATABASE_PATH=homeserver.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 "DB_DEBUG_LEVEL=all" >> packages/home-server/.env
|
|
||||||
echo "REDIS_URL=redis://localhost:6379" >> packages/home-server/.env
|
|
||||||
echo "CACHE_TYPE=${{ matrix.cache_type }}" >> packages/home-server/.env
|
|
||||||
echo "SECONDARY_DB_ENABLED=${{ matrix.secondary_db_enabled }}" >> packages/home-server/.env
|
|
||||||
echo "MONGO_HOST=localhost" >> packages/home-server/.env
|
|
||||||
echo "MONGO_PORT=27017" >> packages/home-server/.env
|
|
||||||
echo "MONGO_DATABASE=standardnotes" >> packages/home-server/.env
|
|
||||||
echo "MONGO_USERNAME=standardnotes" >> packages/home-server/.env
|
|
||||||
echo "MONGO_PASSWORD=standardnotes" >> 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 > logs/output.log 2>&1 &
|
|
||||||
env:
|
|
||||||
PORT: 3123
|
|
||||||
|
|
||||||
- name: Wait for server to start
|
|
||||||
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 3600000 -f http://localhost:9001/mocha/test.html
|
|
||||||
|
|
||||||
- name: Show logs on failure
|
|
||||||
if: ${{ failure() }}
|
|
||||||
run: tail -n 500 logs/output.log
|
|
||||||
|
|||||||
@@ -0,0 +1,128 @@
|
|||||||
|
name: E2E Home Server Test Suite
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
snjs_image_tag:
|
||||||
|
type: string
|
||||||
|
default: latest
|
||||||
|
description: The Docker image tag used for SNJS container
|
||||||
|
suite:
|
||||||
|
type: string
|
||||||
|
default: all
|
||||||
|
description: The test suite to run
|
||||||
|
secrets:
|
||||||
|
DOCKER_USERNAME:
|
||||||
|
required: true
|
||||||
|
DOCKER_PASSWORD:
|
||||||
|
required: true
|
||||||
|
AWS_ACCESS_KEY_ID:
|
||||||
|
required: true
|
||||||
|
AWS_SECRET_ACCESS_KEY:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
e2e-home-server:
|
||||||
|
name: (Home Server) E2E Test Suite
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
db_type: [mysql, sqlite]
|
||||||
|
cache_type: [redis, memory]
|
||||||
|
secondary_db_enabled: [true, false]
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
services:
|
||||||
|
snjs:
|
||||||
|
image: standardnotes/snjs:${{ inputs.snjs_image_tag }}
|
||||||
|
ports:
|
||||||
|
- 9001:9001
|
||||||
|
cache:
|
||||||
|
image: redis
|
||||||
|
ports:
|
||||||
|
- 6379:6379
|
||||||
|
db:
|
||||||
|
image: mysql
|
||||||
|
ports:
|
||||||
|
- 3306:3306
|
||||||
|
env:
|
||||||
|
MYSQL_ROOT_PASSWORD: root
|
||||||
|
MYSQL_DATABASE: standardnotes
|
||||||
|
MYSQL_USER: standardnotes
|
||||||
|
MYSQL_PASSWORD: standardnotes
|
||||||
|
secondary_db:
|
||||||
|
image: mongo:5.0
|
||||||
|
ports:
|
||||||
|
- 27017:27017
|
||||||
|
env:
|
||||||
|
MONGO_INITDB_ROOT_USERNAME: standardnotes
|
||||||
|
MONGO_INITDB_ROOT_PASSWORD: standardnotes
|
||||||
|
MONGO_INITDB_DATABASE: standardnotes
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up Node
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: yarn install --immutable
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: yarn build
|
||||||
|
|
||||||
|
- name: Copy dotenv file
|
||||||
|
run: cp packages/home-server/.env.sample packages/home-server/.env
|
||||||
|
|
||||||
|
- name: Fill in env variables
|
||||||
|
run: |
|
||||||
|
sed -i "s/JWT_SECRET=/JWT_SECRET=$(openssl rand -hex 32)/g" packages/home-server/.env
|
||||||
|
sed -i "s/AUTH_JWT_SECRET=/AUTH_JWT_SECRET=$(openssl rand -hex 32)/g" packages/home-server/.env
|
||||||
|
sed -i "s/ENCRYPTION_SERVER_KEY=/ENCRYPTION_SERVER_KEY=$(openssl rand -hex 32)/g" packages/home-server/.env
|
||||||
|
sed -i "s/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=10" >> packages/home-server/.env
|
||||||
|
echo "REVISIONS_FREQUENCY=2" >> packages/home-server/.env
|
||||||
|
echo "DB_HOST=localhost" >> packages/home-server/.env
|
||||||
|
echo "DB_PORT=3306" >> packages/home-server/.env
|
||||||
|
echo "DB_DATABASE=standardnotes" >> packages/home-server/.env
|
||||||
|
echo "DB_SQLITE_DATABASE_PATH=homeserver.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 "DB_DEBUG_LEVEL=all" >> packages/home-server/.env
|
||||||
|
echo "REDIS_URL=redis://localhost:6379" >> packages/home-server/.env
|
||||||
|
echo "CACHE_TYPE=${{ matrix.cache_type }}" >> packages/home-server/.env
|
||||||
|
echo "SECONDARY_DB_ENABLED=${{ matrix.secondary_db_enabled }}" >> packages/home-server/.env
|
||||||
|
echo "MONGO_HOST=localhost" >> packages/home-server/.env
|
||||||
|
echo "MONGO_PORT=27017" >> packages/home-server/.env
|
||||||
|
echo "MONGO_DATABASE=standardnotes" >> packages/home-server/.env
|
||||||
|
echo "MONGO_USERNAME=standardnotes" >> packages/home-server/.env
|
||||||
|
echo "MONGO_PASSWORD=standardnotes" >> 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 > logs/output.log 2>&1 &
|
||||||
|
env:
|
||||||
|
PORT: 3123
|
||||||
|
|
||||||
|
- name: Wait for server to start
|
||||||
|
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 3600000 -f http://localhost:9001/mocha/test.html?suite=${{ inputs.suite }}
|
||||||
|
|
||||||
|
- name: Archive failed run logs
|
||||||
|
if: ${{ failure() }}
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: home-server-failure-logs-${{ inputs.suite }}-${{ matrix.db_type }}-${{ matrix.cache_type }}-${{ matrix.secondary_db_enabled }}
|
||||||
|
retention-days: 5
|
||||||
|
path: |
|
||||||
|
logs/output.log
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
name: E2E Self Hosted Test Suite
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
snjs_image_tag:
|
||||||
|
type: string
|
||||||
|
default: latest
|
||||||
|
description: The Docker image tag used for SNJS container
|
||||||
|
suite:
|
||||||
|
type: string
|
||||||
|
default: all
|
||||||
|
description: The test suite to run
|
||||||
|
secrets:
|
||||||
|
DOCKER_USERNAME:
|
||||||
|
required: true
|
||||||
|
DOCKER_PASSWORD:
|
||||||
|
required: true
|
||||||
|
AWS_ACCESS_KEY_ID:
|
||||||
|
required: true
|
||||||
|
AWS_SECRET_ACCESS_KEY:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
e2e:
|
||||||
|
name: (Self Hosting) E2E Test Suite
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
secondary_db_enabled: [true, false]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
services:
|
||||||
|
snjs:
|
||||||
|
image: standardnotes/snjs:${{ inputs.snjs_image_tag }}
|
||||||
|
ports:
|
||||||
|
- 9001:9001
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up Node
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
|
||||||
|
- name: Install
|
||||||
|
run: yarn install --immutable
|
||||||
|
|
||||||
|
- name: Run Server
|
||||||
|
run: docker compose -f docker-compose.ci.yml up -d
|
||||||
|
env:
|
||||||
|
DB_TYPE: mysql
|
||||||
|
CACHE_TYPE: redis
|
||||||
|
SECONDARY_DB_ENABLED: ${{ matrix.secondary_db_enabled }}
|
||||||
|
|
||||||
|
- name: Wait for server to start
|
||||||
|
run: docker/is-available.sh http://localhost:3123 $(pwd)/logs
|
||||||
|
|
||||||
|
- name: Run E2E Test Suite
|
||||||
|
run: yarn dlx mocha-headless-chrome --timeout 3600000 -f http://localhost:9001/mocha/test.html?suite=${{ inputs.suite }}
|
||||||
|
|
||||||
|
- name: Archive failed run logs
|
||||||
|
if: ${{ failure() }}
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: self-hosted-failure-logs-${{ inputs.suite }}-${{ matrix.secondary_db_enabled }}
|
||||||
|
retention-days: 5
|
||||||
|
path: |
|
||||||
|
logs/*.err
|
||||||
|
logs/*.log
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
name: E2E Test Suite On Self Hosted Server
|
name: E2E Test Suite
|
||||||
|
|
||||||
run-name: E2E Test Suite against ${{ inputs.ref_name }} by ${{ inputs.author }}
|
run-name: E2E ${{ inputs.suite }} Test Suite against ${{ inputs.ref_name }} by ${{ inputs.author }}
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
@@ -11,6 +11,10 @@ on:
|
|||||||
type: string
|
type: string
|
||||||
default: latest
|
default: latest
|
||||||
description: The Docker image tag used for SNJS container
|
description: The Docker image tag used for SNJS container
|
||||||
|
suite:
|
||||||
|
type: string
|
||||||
|
default: all
|
||||||
|
description: The test suite to run
|
||||||
author:
|
author:
|
||||||
type: string
|
type: string
|
||||||
default: unknown
|
default: unknown
|
||||||
@@ -26,4 +30,5 @@ jobs:
|
|||||||
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
||||||
with:
|
with:
|
||||||
snjs_image_tag: ${{ inputs.snjs_image_tag || 'latest' }}
|
snjs_image_tag: ${{ inputs.snjs_image_tag || 'latest' }}
|
||||||
|
suite: ${{ inputs.suite || 'all' }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|||||||
@@ -95,9 +95,20 @@ jobs:
|
|||||||
- name: Test
|
- name: Test
|
||||||
run: yarn test
|
run: yarn test
|
||||||
|
|
||||||
e2e:
|
e2e-base:
|
||||||
needs: build
|
needs: build
|
||||||
|
name: E2E Base Suite
|
||||||
name: E2E
|
|
||||||
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
||||||
|
with:
|
||||||
|
snjs_image_tag: 'latest'
|
||||||
|
suite: 'base'
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
|
# e2e-vaults:
|
||||||
|
# needs: build
|
||||||
|
# name: E2E Vaults Suite
|
||||||
|
# uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
||||||
|
# with:
|
||||||
|
# snjs_image_tag: 'latest'
|
||||||
|
# suite: 'vaults'
|
||||||
|
# secrets: inherit
|
||||||
|
|||||||
@@ -95,20 +95,32 @@ jobs:
|
|||||||
- name: Test
|
- name: Test
|
||||||
run: yarn test
|
run: yarn test
|
||||||
|
|
||||||
e2e:
|
e2e-base:
|
||||||
needs: build
|
needs: build
|
||||||
name: E2E
|
name: E2E Base Suite
|
||||||
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
||||||
|
with:
|
||||||
|
snjs_image_tag: 'latest'
|
||||||
|
suite: 'base'
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
|
# e2e-vaults:
|
||||||
|
# needs: build
|
||||||
|
# name: E2E Vaults Suite
|
||||||
|
# uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
||||||
|
# with:
|
||||||
|
# snjs_image_tag: 'latest'
|
||||||
|
# suite: 'vaults'
|
||||||
|
# secrets: inherit
|
||||||
|
|
||||||
publish-self-hosting:
|
publish-self-hosting:
|
||||||
needs: [ test, lint, e2e ]
|
needs: [ test, lint, e2e-base ]
|
||||||
name: Publish Self Hosting Docker Image
|
name: Publish Self Hosting Docker Image
|
||||||
uses: standardnotes/server/.github/workflows/common-self-hosting.yml@main
|
uses: standardnotes/server/.github/workflows/common-self-hosting.yml@main
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
publish-services:
|
publish-services:
|
||||||
needs: [ test, lint, e2e ]
|
needs: [ test, lint, e2e-base ]
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
|||||||
@@ -1605,6 +1605,13 @@ const RAW_RUNTIME_STATE =
|
|||||||
["@aws-sdk/service-error-classification", "npm:3.342.0"]\
|
["@aws-sdk/service-error-classification", "npm:3.342.0"]\
|
||||||
],\
|
],\
|
||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
|
}],\
|
||||||
|
["npm:3.370.0", {\
|
||||||
|
"packageLocation": "./.yarn/cache/@aws-sdk-service-error-classification-npm-3.370.0-0d5b615252-500f067ba1.zip/node_modules/@aws-sdk/service-error-classification/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["@aws-sdk/service-error-classification", "npm:3.370.0"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
["@aws-sdk/shared-ini-file-loader", [\
|
["@aws-sdk/shared-ini-file-loader", [\
|
||||||
@@ -1788,6 +1795,15 @@ const RAW_RUNTIME_STATE =
|
|||||||
["tslib", "npm:2.5.2"]\
|
["tslib", "npm:2.5.2"]\
|
||||||
],\
|
],\
|
||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
|
}],\
|
||||||
|
["npm:3.418.0", {\
|
||||||
|
"packageLocation": "./.yarn/cache/@aws-sdk-types-npm-3.418.0-451c0cadd0-627955c2c9.zip/node_modules/@aws-sdk/types/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["@aws-sdk/types", "npm:3.418.0"],\
|
||||||
|
["@smithy/types", "npm:2.3.4"],\
|
||||||
|
["tslib", "npm:2.5.2"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
["@aws-sdk/url-parser", [\
|
["@aws-sdk/url-parser", [\
|
||||||
@@ -5488,6 +5504,14 @@ const RAW_RUNTIME_STATE =
|
|||||||
["tslib", "npm:2.5.2"]\
|
["tslib", "npm:2.5.2"]\
|
||||||
],\
|
],\
|
||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
|
}],\
|
||||||
|
["npm:2.3.4", {\
|
||||||
|
"packageLocation": "./.yarn/cache/@smithy-types-npm-2.3.4-7d0b3a2a2f-8a5ad3b47e.zip/node_modules/@smithy/types/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["@smithy/types", "npm:2.3.4"],\
|
||||||
|
["tslib", "npm:2.5.2"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
["@smithy/url-parser", [\
|
["@smithy/url-parser", [\
|
||||||
@@ -5773,6 +5797,7 @@ const RAW_RUNTIME_STATE =
|
|||||||
["@types/prettyjson", "npm:0.0.30"],\
|
["@types/prettyjson", "npm:0.0.30"],\
|
||||||
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
||||||
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
||||||
|
["aws-xray-sdk", "npm:3.5.2"],\
|
||||||
["axios", "npm:1.4.0"],\
|
["axios", "npm:1.4.0"],\
|
||||||
["cors", "npm:2.8.5"],\
|
["cors", "npm:2.8.5"],\
|
||||||
["dotenv", "npm:16.1.3"],\
|
["dotenv", "npm:16.1.3"],\
|
||||||
@@ -5835,6 +5860,7 @@ const RAW_RUNTIME_STATE =
|
|||||||
["@types/uuid", "npm:9.0.3"],\
|
["@types/uuid", "npm:9.0.3"],\
|
||||||
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
||||||
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
||||||
|
["aws-xray-sdk", "npm:3.5.2"],\
|
||||||
["axios", "npm:1.4.0"],\
|
["axios", "npm:1.4.0"],\
|
||||||
["bcryptjs", "npm:2.4.3"],\
|
["bcryptjs", "npm:2.4.3"],\
|
||||||
["cors", "npm:2.8.5"],\
|
["cors", "npm:2.8.5"],\
|
||||||
@@ -5938,6 +5964,7 @@ const RAW_RUNTIME_STATE =
|
|||||||
["@types/newrelic", "npm:9.14.0"],\
|
["@types/newrelic", "npm:9.14.0"],\
|
||||||
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
||||||
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
||||||
|
["aws-xray-sdk", "npm:3.5.2"],\
|
||||||
["eslint", "npm:8.41.0"],\
|
["eslint", "npm:8.41.0"],\
|
||||||
["eslint-plugin-prettier", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.0.0"],\
|
["eslint-plugin-prettier", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.0.0"],\
|
||||||
["ioredis", "npm:5.3.2"],\
|
["ioredis", "npm:5.3.2"],\
|
||||||
@@ -6027,6 +6054,7 @@ const RAW_RUNTIME_STATE =
|
|||||||
["@types/uuid", "npm:9.0.3"],\
|
["@types/uuid", "npm:9.0.3"],\
|
||||||
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
||||||
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
||||||
|
["aws-xray-sdk", "npm:3.5.2"],\
|
||||||
["connect-busboy", "npm:1.0.0"],\
|
["connect-busboy", "npm:1.0.0"],\
|
||||||
["cors", "npm:2.8.5"],\
|
["cors", "npm:2.8.5"],\
|
||||||
["dayjs", "npm:1.11.7"],\
|
["dayjs", "npm:1.11.7"],\
|
||||||
@@ -6158,10 +6186,12 @@ const RAW_RUNTIME_STATE =
|
|||||||
["@types/express", "npm:4.17.17"],\
|
["@types/express", "npm:4.17.17"],\
|
||||||
["@types/ioredis", "npm:5.0.0"],\
|
["@types/ioredis", "npm:5.0.0"],\
|
||||||
["@types/jest", "npm:29.5.2"],\
|
["@types/jest", "npm:29.5.2"],\
|
||||||
|
["@types/mysql", "npm:2.15.22"],\
|
||||||
["@types/newrelic", "npm:9.14.0"],\
|
["@types/newrelic", "npm:9.14.0"],\
|
||||||
["@types/node", "npm:20.5.7"],\
|
["@types/node", "npm:20.5.7"],\
|
||||||
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
||||||
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
||||||
|
["aws-xray-sdk", "npm:3.5.2"],\
|
||||||
["cors", "npm:2.8.5"],\
|
["cors", "npm:2.8.5"],\
|
||||||
["dotenv", "npm:16.1.3"],\
|
["dotenv", "npm:16.1.3"],\
|
||||||
["eslint", "npm:8.41.0"],\
|
["eslint", "npm:8.41.0"],\
|
||||||
@@ -6172,6 +6202,7 @@ const RAW_RUNTIME_STATE =
|
|||||||
["ioredis", "npm:5.3.2"],\
|
["ioredis", "npm:5.3.2"],\
|
||||||
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.5.0"],\
|
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.5.0"],\
|
||||||
["mongodb", "virtual:365b8c88cdf194291829ee28b79556e2328175d26a621363e703848100bea0042e9500db2a1206c9bbc3a4a76a1d169639ef774b2ea3a1a98584a9936b58c6be#npm:6.0.0"],\
|
["mongodb", "virtual:365b8c88cdf194291829ee28b79556e2328175d26a621363e703848100bea0042e9500db2a1206c9bbc3a4a76a1d169639ef774b2ea3a1a98584a9936b58c6be#npm:6.0.0"],\
|
||||||
|
["mysql", "npm:2.18.1"],\
|
||||||
["mysql2", "npm:3.3.3"],\
|
["mysql2", "npm:3.3.3"],\
|
||||||
["newrelic", "npm:11.0.0"],\
|
["newrelic", "npm:11.0.0"],\
|
||||||
["prettier", "npm:3.0.3"],\
|
["prettier", "npm:3.0.3"],\
|
||||||
@@ -6353,6 +6384,7 @@ const RAW_RUNTIME_STATE =
|
|||||||
["@types/uuid", "npm:9.0.3"],\
|
["@types/uuid", "npm:9.0.3"],\
|
||||||
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
||||||
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
|
||||||
|
["aws-xray-sdk", "npm:3.5.2"],\
|
||||||
["axios", "npm:1.4.0"],\
|
["axios", "npm:1.4.0"],\
|
||||||
["cors", "npm:2.8.5"],\
|
["cors", "npm:2.8.5"],\
|
||||||
["dotenv", "npm:16.1.3"],\
|
["dotenv", "npm:16.1.3"],\
|
||||||
@@ -6609,6 +6641,16 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["@types/cls-hooked", [\
|
||||||
|
["npm:4.3.6", {\
|
||||||
|
"packageLocation": "./.yarn/cache/@types-cls-hooked-npm-4.3.6-8787b64e86-f5b9864348.zip/node_modules/@types/cls-hooked/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["@types/cls-hooked", "npm:4.3.6"],\
|
||||||
|
["@types/node", "npm:20.2.5"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["@types/concat-stream", [\
|
["@types/concat-stream", [\
|
||||||
["npm:1.6.1", {\
|
["npm:1.6.1", {\
|
||||||
"packageLocation": "./.yarn/cache/@types-concat-stream-npm-1.6.1-42cd06b019-7d211e7433.zip/node_modules/@types/concat-stream/",\
|
"packageLocation": "./.yarn/cache/@types-concat-stream-npm-1.6.1-42cd06b019-7d211e7433.zip/node_modules/@types/concat-stream/",\
|
||||||
@@ -6868,6 +6910,16 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["@types/mysql", [\
|
||||||
|
["npm:2.15.22", {\
|
||||||
|
"packageLocation": "./.yarn/cache/@types-mysql-npm-2.15.22-d643eb999e-6be0aac58f.zip/node_modules/@types/mysql/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["@types/mysql", "npm:2.15.22"],\
|
||||||
|
["@types/node", "npm:20.2.5"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["@types/newrelic", [\
|
["@types/newrelic", [\
|
||||||
["npm:9.14.0", {\
|
["npm:9.14.0", {\
|
||||||
"packageLocation": "./.yarn/cache/@types-newrelic-npm-9.14.0-4668da51a1-3a54ea75a4.zip/node_modules/@types/newrelic/",\
|
"packageLocation": "./.yarn/cache/@types-newrelic-npm-9.14.0-4668da51a1-3a54ea75a4.zip/node_modules/@types/newrelic/",\
|
||||||
@@ -6936,6 +6988,18 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["@types/pg", [\
|
||||||
|
["npm:8.10.3", {\
|
||||||
|
"packageLocation": "./.yarn/cache/@types-pg-npm-8.10.3-3fc3365c7b-22d4836bd9.zip/node_modules/@types/pg/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["@types/pg", "npm:8.10.3"],\
|
||||||
|
["@types/node", "npm:20.2.5"],\
|
||||||
|
["pg-protocol", "npm:1.6.0"],\
|
||||||
|
["pg-types", "npm:4.0.1"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["@types/prettier", [\
|
["@types/prettier", [\
|
||||||
["npm:2.7.3", {\
|
["npm:2.7.3", {\
|
||||||
"packageLocation": "./.yarn/cache/@types-prettier-npm-2.7.3-497316f37c-cda84c19ac.zip/node_modules/@types/prettier/",\
|
"packageLocation": "./.yarn/cache/@types-prettier-npm-2.7.3-497316f37c-cda84c19ac.zip/node_modules/@types/prettier/",\
|
||||||
@@ -7946,6 +8010,16 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["async-hook-jl", [\
|
||||||
|
["npm:1.7.6", {\
|
||||||
|
"packageLocation": "./.yarn/cache/async-hook-jl-npm-1.7.6-9999815029-f61a3bd4c3.zip/node_modules/async-hook-jl/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["async-hook-jl", "npm:1.7.6"],\
|
||||||
|
["stack-chain", "npm:1.3.7"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["asynckit", [\
|
["asynckit", [\
|
||||||
["npm:0.4.0", {\
|
["npm:0.4.0", {\
|
||||||
"packageLocation": "./.yarn/cache/asynckit-npm-0.4.0-c718858525-3ce727cbc7.zip/node_modules/asynckit/",\
|
"packageLocation": "./.yarn/cache/asynckit-npm-0.4.0-c718858525-3ce727cbc7.zip/node_modules/asynckit/",\
|
||||||
@@ -7955,6 +8029,112 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["atomic-batcher", [\
|
||||||
|
["npm:1.0.2", {\
|
||||||
|
"packageLocation": "./.yarn/cache/atomic-batcher-npm-1.0.2-6fcd3a3097-025e334f1f.zip/node_modules/atomic-batcher/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["atomic-batcher", "npm:1.0.2"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
|
["aws-xray-sdk", [\
|
||||||
|
["npm:3.5.2", {\
|
||||||
|
"packageLocation": "./.yarn/cache/aws-xray-sdk-npm-3.5.2-15fc4e54ee-576d0d5ccb.zip/node_modules/aws-xray-sdk/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["aws-xray-sdk", "npm:3.5.2"],\
|
||||||
|
["aws-xray-sdk-core", "npm:3.5.2"],\
|
||||||
|
["aws-xray-sdk-express", "virtual:15fc4e54eec18d85ce3f22aa2405619072c35fbd500ad809cce2c9e4ead8a191fcc189cef6a5d76df3bea5576f09735fc4d32f086db561623afc56dd36794c8f#npm:3.5.2"],\
|
||||||
|
["aws-xray-sdk-mysql", "virtual:15fc4e54eec18d85ce3f22aa2405619072c35fbd500ad809cce2c9e4ead8a191fcc189cef6a5d76df3bea5576f09735fc4d32f086db561623afc56dd36794c8f#npm:3.5.2"],\
|
||||||
|
["aws-xray-sdk-postgres", "virtual:15fc4e54eec18d85ce3f22aa2405619072c35fbd500ad809cce2c9e4ead8a191fcc189cef6a5d76df3bea5576f09735fc4d32f086db561623afc56dd36794c8f#npm:3.5.2"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
|
["aws-xray-sdk-core", [\
|
||||||
|
["npm:3.5.2", {\
|
||||||
|
"packageLocation": "./.yarn/cache/aws-xray-sdk-core-npm-3.5.2-9083a0c00f-a643998187.zip/node_modules/aws-xray-sdk-core/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["aws-xray-sdk-core", "npm:3.5.2"],\
|
||||||
|
["@aws-sdk/service-error-classification", "npm:3.370.0"],\
|
||||||
|
["@aws-sdk/types", "npm:3.418.0"],\
|
||||||
|
["@types/cls-hooked", "npm:4.3.6"],\
|
||||||
|
["atomic-batcher", "npm:1.0.2"],\
|
||||||
|
["cls-hooked", "npm:4.2.2"],\
|
||||||
|
["semver", "npm:7.5.4"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
|
["aws-xray-sdk-express", [\
|
||||||
|
["npm:3.5.2", {\
|
||||||
|
"packageLocation": "./.yarn/cache/aws-xray-sdk-express-npm-3.5.2-c4574a664b-62a07d0f3b.zip/node_modules/aws-xray-sdk-express/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["aws-xray-sdk-express", "npm:3.5.2"]\
|
||||||
|
],\
|
||||||
|
"linkType": "SOFT"\
|
||||||
|
}],\
|
||||||
|
["virtual:15fc4e54eec18d85ce3f22aa2405619072c35fbd500ad809cce2c9e4ead8a191fcc189cef6a5d76df3bea5576f09735fc4d32f086db561623afc56dd36794c8f#npm:3.5.2", {\
|
||||||
|
"packageLocation": "./.yarn/__virtual__/aws-xray-sdk-express-virtual-36027c3d91/0/cache/aws-xray-sdk-express-npm-3.5.2-c4574a664b-62a07d0f3b.zip/node_modules/aws-xray-sdk-express/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["aws-xray-sdk-express", "virtual:15fc4e54eec18d85ce3f22aa2405619072c35fbd500ad809cce2c9e4ead8a191fcc189cef6a5d76df3bea5576f09735fc4d32f086db561623afc56dd36794c8f#npm:3.5.2"],\
|
||||||
|
["@types/aws-xray-sdk-core", null],\
|
||||||
|
["@types/express", "npm:4.17.17"],\
|
||||||
|
["aws-xray-sdk-core", "npm:3.5.2"]\
|
||||||
|
],\
|
||||||
|
"packagePeers": [\
|
||||||
|
"@types/aws-xray-sdk-core",\
|
||||||
|
"aws-xray-sdk-core"\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
|
["aws-xray-sdk-mysql", [\
|
||||||
|
["npm:3.5.2", {\
|
||||||
|
"packageLocation": "./.yarn/cache/aws-xray-sdk-mysql-npm-3.5.2-095483ab95-f910a96630.zip/node_modules/aws-xray-sdk-mysql/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["aws-xray-sdk-mysql", "npm:3.5.2"]\
|
||||||
|
],\
|
||||||
|
"linkType": "SOFT"\
|
||||||
|
}],\
|
||||||
|
["virtual:15fc4e54eec18d85ce3f22aa2405619072c35fbd500ad809cce2c9e4ead8a191fcc189cef6a5d76df3bea5576f09735fc4d32f086db561623afc56dd36794c8f#npm:3.5.2", {\
|
||||||
|
"packageLocation": "./.yarn/__virtual__/aws-xray-sdk-mysql-virtual-d8a5f29b75/0/cache/aws-xray-sdk-mysql-npm-3.5.2-095483ab95-f910a96630.zip/node_modules/aws-xray-sdk-mysql/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["aws-xray-sdk-mysql", "virtual:15fc4e54eec18d85ce3f22aa2405619072c35fbd500ad809cce2c9e4ead8a191fcc189cef6a5d76df3bea5576f09735fc4d32f086db561623afc56dd36794c8f#npm:3.5.2"],\
|
||||||
|
["@types/aws-xray-sdk-core", null],\
|
||||||
|
["@types/mysql", "npm:2.15.22"],\
|
||||||
|
["aws-xray-sdk-core", "npm:3.5.2"]\
|
||||||
|
],\
|
||||||
|
"packagePeers": [\
|
||||||
|
"@types/aws-xray-sdk-core",\
|
||||||
|
"aws-xray-sdk-core"\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
|
["aws-xray-sdk-postgres", [\
|
||||||
|
["npm:3.5.2", {\
|
||||||
|
"packageLocation": "./.yarn/cache/aws-xray-sdk-postgres-npm-3.5.2-3a7e7bcc42-f2d6da22c7.zip/node_modules/aws-xray-sdk-postgres/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["aws-xray-sdk-postgres", "npm:3.5.2"]\
|
||||||
|
],\
|
||||||
|
"linkType": "SOFT"\
|
||||||
|
}],\
|
||||||
|
["virtual:15fc4e54eec18d85ce3f22aa2405619072c35fbd500ad809cce2c9e4ead8a191fcc189cef6a5d76df3bea5576f09735fc4d32f086db561623afc56dd36794c8f#npm:3.5.2", {\
|
||||||
|
"packageLocation": "./.yarn/__virtual__/aws-xray-sdk-postgres-virtual-c6edb063fc/0/cache/aws-xray-sdk-postgres-npm-3.5.2-3a7e7bcc42-f2d6da22c7.zip/node_modules/aws-xray-sdk-postgres/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["aws-xray-sdk-postgres", "virtual:15fc4e54eec18d85ce3f22aa2405619072c35fbd500ad809cce2c9e4ead8a191fcc189cef6a5d76df3bea5576f09735fc4d32f086db561623afc56dd36794c8f#npm:3.5.2"],\
|
||||||
|
["@types/aws-xray-sdk-core", null],\
|
||||||
|
["@types/pg", "npm:8.10.3"],\
|
||||||
|
["aws-xray-sdk-core", "npm:3.5.2"]\
|
||||||
|
],\
|
||||||
|
"packagePeers": [\
|
||||||
|
"@types/aws-xray-sdk-core",\
|
||||||
|
"aws-xray-sdk-core"\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["axios", [\
|
["axios", [\
|
||||||
["npm:0.21.4", {\
|
["npm:0.21.4", {\
|
||||||
"packageLocation": "./.yarn/cache/axios-npm-0.21.4-e278873748-da644592cb.zip/node_modules/axios/",\
|
"packageLocation": "./.yarn/cache/axios-npm-0.21.4-e278873748-da644592cb.zip/node_modules/axios/",\
|
||||||
@@ -8158,6 +8338,13 @@ const RAW_RUNTIME_STATE =
|
|||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
["bignumber.js", [\
|
["bignumber.js", [\
|
||||||
|
["npm:9.0.0", {\
|
||||||
|
"packageLocation": "./.yarn/cache/bignumber.js-npm-9.0.0-ce190bcd7c-7406d0d11d.zip/node_modules/bignumber.js/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["bignumber.js", "npm:9.0.0"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}],\
|
||||||
["npm:9.1.1", {\
|
["npm:9.1.1", {\
|
||||||
"packageLocation": "./.yarn/cache/bignumber.js-npm-9.1.1-5929e8d8dc-1f771bfa88.zip/node_modules/bignumber.js/",\
|
"packageLocation": "./.yarn/cache/bignumber.js-npm-9.1.1-5929e8d8dc-1f771bfa88.zip/node_modules/bignumber.js/",\
|
||||||
"packageDependencies": [\
|
"packageDependencies": [\
|
||||||
@@ -8745,6 +8932,18 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["cls-hooked", [\
|
||||||
|
["npm:4.2.2", {\
|
||||||
|
"packageLocation": "./.yarn/cache/cls-hooked-npm-4.2.2-db33b9b95f-59081fcc0f.zip/node_modules/cls-hooked/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["cls-hooked", "npm:4.2.2"],\
|
||||||
|
["async-hook-jl", "npm:1.7.6"],\
|
||||||
|
["emitter-listener", "npm:1.1.2"],\
|
||||||
|
["semver", "npm:5.7.2"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["cluster-key-slot", [\
|
["cluster-key-slot", [\
|
||||||
["npm:1.1.2", {\
|
["npm:1.1.2", {\
|
||||||
"packageLocation": "./.yarn/cache/cluster-key-slot-npm-1.1.2-0571a28825-516ed8b5e1.zip/node_modules/cluster-key-slot/",\
|
"packageLocation": "./.yarn/cache/cluster-key-slot-npm-1.1.2-0571a28825-516ed8b5e1.zip/node_modules/cluster-key-slot/",\
|
||||||
@@ -9635,6 +9834,16 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["emitter-listener", [\
|
||||||
|
["npm:1.1.2", {\
|
||||||
|
"packageLocation": "./.yarn/cache/emitter-listener-npm-1.1.2-0fe118d0b3-697f53c308.zip/node_modules/emitter-listener/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["emitter-listener", "npm:1.1.2"],\
|
||||||
|
["shimmer", "npm:1.2.1"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["emittery", [\
|
["emittery", [\
|
||||||
["npm:0.13.1", {\
|
["npm:0.13.1", {\
|
||||||
"packageLocation": "./.yarn/cache/emittery-npm-0.13.1-cb6cd1bb03-fbe214171d.zip/node_modules/emittery/",\
|
"packageLocation": "./.yarn/cache/emittery-npm-0.13.1-cb6cd1bb03-fbe214171d.zip/node_modules/emittery/",\
|
||||||
@@ -13518,6 +13727,19 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["mysql", [\
|
||||||
|
["npm:2.18.1", {\
|
||||||
|
"packageLocation": "./.yarn/cache/mysql-npm-2.18.1-8fdb56201f-87d80e3747.zip/node_modules/mysql/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["mysql", "npm:2.18.1"],\
|
||||||
|
["bignumber.js", "npm:9.0.0"],\
|
||||||
|
["readable-stream", "npm:2.3.7"],\
|
||||||
|
["safe-buffer", "npm:5.1.2"],\
|
||||||
|
["sqlstring", "npm:2.3.1"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["mysql2", [\
|
["mysql2", [\
|
||||||
["npm:3.3.3", {\
|
["npm:3.3.3", {\
|
||||||
"packageLocation": "./.yarn/cache/mysql2-npm-3.3.3-d2fe8cf512-4bf7ace8f1.zip/node_modules/mysql2/",\
|
"packageLocation": "./.yarn/cache/mysql2-npm-3.3.3-d2fe8cf512-4bf7ace8f1.zip/node_modules/mysql2/",\
|
||||||
@@ -14007,6 +14229,15 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["obuf", [\
|
||||||
|
["npm:1.1.2", {\
|
||||||
|
"packageLocation": "./.yarn/cache/obuf-npm-1.1.2-8db5fae8dd-53ff4ab3a1.zip/node_modules/obuf/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["obuf", "npm:1.1.2"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["on-finished", [\
|
["on-finished", [\
|
||||||
["npm:2.4.1", {\
|
["npm:2.4.1", {\
|
||||||
"packageLocation": "./.yarn/cache/on-finished-npm-2.4.1-907af70f88-8e81472c50.zip/node_modules/on-finished/",\
|
"packageLocation": "./.yarn/cache/on-finished-npm-2.4.1-907af70f88-8e81472c50.zip/node_modules/on-finished/",\
|
||||||
@@ -14467,6 +14698,49 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["pg-int8", [\
|
||||||
|
["npm:1.0.1", {\
|
||||||
|
"packageLocation": "./.yarn/cache/pg-int8-npm-1.0.1-5cd67f3e22-a1e3a05a69.zip/node_modules/pg-int8/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["pg-int8", "npm:1.0.1"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
|
["pg-numeric", [\
|
||||||
|
["npm:1.0.2", {\
|
||||||
|
"packageLocation": "./.yarn/cache/pg-numeric-npm-1.0.2-9026ec3427-8899f8200c.zip/node_modules/pg-numeric/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["pg-numeric", "npm:1.0.2"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
|
["pg-protocol", [\
|
||||||
|
["npm:1.6.0", {\
|
||||||
|
"packageLocation": "./.yarn/cache/pg-protocol-npm-1.6.0-089a4b1d3c-995864cc2a.zip/node_modules/pg-protocol/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["pg-protocol", "npm:1.6.0"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
|
["pg-types", [\
|
||||||
|
["npm:4.0.1", {\
|
||||||
|
"packageLocation": "./.yarn/cache/pg-types-npm-4.0.1-8f922557d3-2c686ef361.zip/node_modules/pg-types/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["pg-types", "npm:4.0.1"],\
|
||||||
|
["pg-int8", "npm:1.0.1"],\
|
||||||
|
["pg-numeric", "npm:1.0.2"],\
|
||||||
|
["postgres-array", "npm:3.0.2"],\
|
||||||
|
["postgres-bytea", "npm:3.0.0"],\
|
||||||
|
["postgres-date", "npm:2.0.1"],\
|
||||||
|
["postgres-interval", "npm:3.0.0"],\
|
||||||
|
["postgres-range", "npm:1.1.3"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["picocolors", [\
|
["picocolors", [\
|
||||||
["npm:1.0.0", {\
|
["npm:1.0.0", {\
|
||||||
"packageLocation": "./.yarn/cache/picocolors-npm-1.0.0-d81e0b1927-a2e8092dd8.zip/node_modules/picocolors/",\
|
"packageLocation": "./.yarn/cache/picocolors-npm-1.0.0-d81e0b1927-a2e8092dd8.zip/node_modules/picocolors/",\
|
||||||
@@ -14538,6 +14812,52 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["postgres-array", [\
|
||||||
|
["npm:3.0.2", {\
|
||||||
|
"packageLocation": "./.yarn/cache/postgres-array-npm-3.0.2-da6a3f1fed-0159517e4e.zip/node_modules/postgres-array/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["postgres-array", "npm:3.0.2"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
|
["postgres-bytea", [\
|
||||||
|
["npm:3.0.0", {\
|
||||||
|
"packageLocation": "./.yarn/cache/postgres-bytea-npm-3.0.0-5de4c664f6-f5c01758fd.zip/node_modules/postgres-bytea/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["postgres-bytea", "npm:3.0.0"],\
|
||||||
|
["obuf", "npm:1.1.2"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
|
["postgres-date", [\
|
||||||
|
["npm:2.0.1", {\
|
||||||
|
"packageLocation": "./.yarn/cache/postgres-date-npm-2.0.1-00e0e0bc9e-908eacec35.zip/node_modules/postgres-date/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["postgres-date", "npm:2.0.1"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
|
["postgres-interval", [\
|
||||||
|
["npm:3.0.0", {\
|
||||||
|
"packageLocation": "./.yarn/cache/postgres-interval-npm-3.0.0-936c769b98-c7a1cf006d.zip/node_modules/postgres-interval/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["postgres-interval", "npm:3.0.0"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
|
["postgres-range", [\
|
||||||
|
["npm:1.1.3", {\
|
||||||
|
"packageLocation": "./.yarn/cache/postgres-range-npm-1.1.3-46f68e1a9e-356a46d97e.zip/node_modules/postgres-range/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["postgres-range", "npm:1.1.3"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["prelude-ls", [\
|
["prelude-ls", [\
|
||||||
["npm:1.2.1", {\
|
["npm:1.2.1", {\
|
||||||
"packageLocation": "./.yarn/cache/prelude-ls-npm-1.2.1-3e4d272a55-0b9d2c7680.zip/node_modules/prelude-ls/",\
|
"packageLocation": "./.yarn/cache/prelude-ls-npm-1.2.1-3e4d272a55-0b9d2c7680.zip/node_modules/prelude-ls/",\
|
||||||
@@ -14957,6 +15277,20 @@ const RAW_RUNTIME_STATE =
|
|||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
["readable-stream", [\
|
["readable-stream", [\
|
||||||
|
["npm:2.3.7", {\
|
||||||
|
"packageLocation": "./.yarn/cache/readable-stream-npm-2.3.7-77b22a9818-d04c677c17.zip/node_modules/readable-stream/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["readable-stream", "npm:2.3.7"],\
|
||||||
|
["core-util-is", "npm:1.0.3"],\
|
||||||
|
["inherits", "npm:2.0.4"],\
|
||||||
|
["isarray", "npm:1.0.0"],\
|
||||||
|
["process-nextick-args", "npm:2.0.1"],\
|
||||||
|
["safe-buffer", "npm:5.1.2"],\
|
||||||
|
["string_decoder", "npm:1.1.1"],\
|
||||||
|
["util-deprecate", "npm:1.0.2"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}],\
|
||||||
["npm:2.3.8", {\
|
["npm:2.3.8", {\
|
||||||
"packageLocation": "./.yarn/cache/readable-stream-npm-2.3.8-67a94c2cb1-8500dd3a90.zip/node_modules/readable-stream/",\
|
"packageLocation": "./.yarn/cache/readable-stream-npm-2.3.8-67a94c2cb1-8500dd3a90.zip/node_modules/readable-stream/",\
|
||||||
"packageDependencies": [\
|
"packageDependencies": [\
|
||||||
@@ -15297,6 +15631,13 @@ const RAW_RUNTIME_STATE =
|
|||||||
],\
|
],\
|
||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}],\
|
}],\
|
||||||
|
["npm:5.7.2", {\
|
||||||
|
"packageLocation": "./.yarn/cache/semver-npm-5.7.2-938ee91eaa-fca14418a1.zip/node_modules/semver/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["semver", "npm:5.7.2"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}],\
|
||||||
["npm:6.3.0", {\
|
["npm:6.3.0", {\
|
||||||
"packageLocation": "./.yarn/cache/semver-npm-6.3.0-b3eace8bfd-8dd72e7c7c.zip/node_modules/semver/",\
|
"packageLocation": "./.yarn/cache/semver-npm-6.3.0-b3eace8bfd-8dd72e7c7c.zip/node_modules/semver/",\
|
||||||
"packageDependencies": [\
|
"packageDependencies": [\
|
||||||
@@ -15441,6 +15782,15 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["shimmer", [\
|
||||||
|
["npm:1.2.1", {\
|
||||||
|
"packageLocation": "./.yarn/cache/shimmer-npm-1.2.1-8b50bf3206-aa0d6252ad.zip/node_modules/shimmer/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["shimmer", "npm:1.2.1"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["side-channel", [\
|
["side-channel", [\
|
||||||
["npm:1.0.4", {\
|
["npm:1.0.4", {\
|
||||||
"packageLocation": "./.yarn/cache/side-channel-npm-1.0.4-e1f38b9e06-c4998d9fc5.zip/node_modules/side-channel/",\
|
"packageLocation": "./.yarn/cache/side-channel-npm-1.0.4-e1f38b9e06-c4998d9fc5.zip/node_modules/side-channel/",\
|
||||||
@@ -15708,6 +16058,13 @@ const RAW_RUNTIME_STATE =
|
|||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
["sqlstring", [\
|
["sqlstring", [\
|
||||||
|
["npm:2.3.1", {\
|
||||||
|
"packageLocation": "./.yarn/cache/sqlstring-npm-2.3.1-2d4ffafe98-bc09237002.zip/node_modules/sqlstring/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["sqlstring", "npm:2.3.1"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}],\
|
||||||
["npm:2.3.3", {\
|
["npm:2.3.3", {\
|
||||||
"packageLocation": "./.yarn/cache/sqlstring-npm-2.3.3-2db6939570-4e5a25af2d.zip/node_modules/sqlstring/",\
|
"packageLocation": "./.yarn/cache/sqlstring-npm-2.3.3-2db6939570-4e5a25af2d.zip/node_modules/sqlstring/",\
|
||||||
"packageDependencies": [\
|
"packageDependencies": [\
|
||||||
@@ -15765,6 +16122,15 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["stack-chain", [\
|
||||||
|
["npm:1.3.7", {\
|
||||||
|
"packageLocation": "./.yarn/cache/stack-chain-npm-1.3.7-c803ef2abb-6420637b76.zip/node_modules/stack-chain/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["stack-chain", "npm:1.3.7"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["stack-trace", [\
|
["stack-trace", [\
|
||||||
["npm:0.0.10", {\
|
["npm:0.0.10", {\
|
||||||
"packageLocation": "./.yarn/cache/stack-trace-npm-0.0.10-9460b173e1-7bd633f0e9.zip/node_modules/stack-trace/",\
|
"packageLocation": "./.yarn/cache/stack-trace-npm-0.0.10-9460b173e1-7bd633f0e9.zip/node_modules/stack-trace/",\
|
||||||
|
|||||||
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -3,6 +3,46 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [2.27.10](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.27.9...@standardnotes/analytics@2.27.10) (2023-10-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.27.9](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.27.8...@standardnotes/analytics@2.27.9) (2023-10-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.27.8](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.27.7...@standardnotes/analytics@2.27.8) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.27.7](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.27.6...@standardnotes/analytics@2.27.7) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.27.6](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.27.5...@standardnotes/analytics@2.27.6) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.27.5](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.27.4...@standardnotes/analytics@2.27.5) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.27.4](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.27.3...@standardnotes/analytics@2.27.4) (2023-10-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.27.3](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.27.2...@standardnotes/analytics@2.27.3) (2023-10-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.27.2](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.27.1...@standardnotes/analytics@2.27.2) (2023-09-28)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.27.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.27.0...@standardnotes/analytics@2.27.1) (2023-09-27)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
# [2.27.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.26.24...@standardnotes/analytics@2.27.0) (2023-09-26)
|
# [2.27.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.26.24...@standardnotes/analytics@2.27.0) (2023-09-26)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/analytics",
|
"name": "@standardnotes/analytics",
|
||||||
"version": "2.27.0",
|
"version": "2.27.10",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,52 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.76.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.76.1...@standardnotes/api-gateway@1.76.2) (2023-10-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.76.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.76.0...@standardnotes/api-gateway@1.76.1) (2023-10-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
# [1.76.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.75.13...@standardnotes/api-gateway@1.76.0) (2023-10-04)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **api-gateaway:** configure aws-xray-sdk ([dc76113](https://github.com/standardnotes/api-gateway/commit/dc7611391515dd49a8e9b7ce8ac5e128cd7af0a8))
|
||||||
|
|
||||||
|
## [1.75.13](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.75.12...@standardnotes/api-gateway@1.75.13) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.75.12](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.75.11...@standardnotes/api-gateway@1.75.12) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.75.11](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.75.10...@standardnotes/api-gateway@1.75.11) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.75.10](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.75.9...@standardnotes/api-gateway@1.75.10) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.75.9](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.75.8...@standardnotes/api-gateway@1.75.9) (2023-10-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.75.8](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.75.7...@standardnotes/api-gateway@1.75.8) (2023-10-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.75.7](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.75.6...@standardnotes/api-gateway@1.75.7) (2023-09-28)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.75.6](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.75.5...@standardnotes/api-gateway@1.75.6) (2023-09-27)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
## [1.75.5](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.75.4...@standardnotes/api-gateway@1.75.5) (2023-09-26)
|
## [1.75.5](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.75.4...@standardnotes/api-gateway@1.75.5) (2023-09-26)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import helmet from 'helmet'
|
|||||||
import * as cors from 'cors'
|
import * as cors from 'cors'
|
||||||
import { text, json, Request, Response, NextFunction } from 'express'
|
import { text, json, Request, Response, NextFunction } from 'express'
|
||||||
import * as winston from 'winston'
|
import * as winston from 'winston'
|
||||||
|
import * as AWSXRay from 'aws-xray-sdk'
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const robots = require('express-robots-txt')
|
const robots = require('express-robots-txt')
|
||||||
|
|
||||||
@@ -36,15 +37,27 @@ import { InversifyExpressServer } from 'inversify-express-utils'
|
|||||||
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
||||||
import { TYPES } from '../src/Bootstrap/Types'
|
import { TYPES } from '../src/Bootstrap/Types'
|
||||||
import { Env } from '../src/Bootstrap/Env'
|
import { Env } from '../src/Bootstrap/Env'
|
||||||
|
import { ServiceIdentifier } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
const container = new ContainerConfigLoader()
|
const container = new ContainerConfigLoader()
|
||||||
void container.load().then((container) => {
|
void container.load().then((container) => {
|
||||||
const env: Env = new Env()
|
const env: Env = new Env()
|
||||||
env.load()
|
env.load()
|
||||||
|
|
||||||
|
const isConfiguredForAWSProduction =
|
||||||
|
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
|
||||||
|
|
||||||
|
if (isConfiguredForAWSProduction) {
|
||||||
|
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
|
||||||
|
}
|
||||||
|
|
||||||
const server = new InversifyExpressServer(container)
|
const server = new InversifyExpressServer(container)
|
||||||
|
|
||||||
server.setConfig((app) => {
|
server.setConfig((app) => {
|
||||||
|
if (isConfiguredForAWSProduction) {
|
||||||
|
app.use(AWSXRay.express.openSegment(ServiceIdentifier.NAMES.ApiGateway))
|
||||||
|
}
|
||||||
|
|
||||||
app.use((_request: Request, response: Response, next: NextFunction) => {
|
app.use((_request: Request, response: Response, next: NextFunction) => {
|
||||||
response.setHeader('X-API-Gateway-Version', container.get(TYPES.ApiGateway_VERSION))
|
response.setHeader('X-API-Gateway-Version', container.get(TYPES.ApiGateway_VERSION))
|
||||||
next()
|
next()
|
||||||
@@ -104,6 +117,10 @@ void container.load().then((container) => {
|
|||||||
|
|
||||||
const serverInstance = server.build()
|
const serverInstance = server.build()
|
||||||
|
|
||||||
|
if (isConfiguredForAWSProduction) {
|
||||||
|
serverInstance.use(AWSXRay.express.closeSegment())
|
||||||
|
}
|
||||||
|
|
||||||
serverInstance.listen(env.get('PORT'))
|
serverInstance.listen(env.get('PORT'))
|
||||||
|
|
||||||
logger.info(`Server started on port ${process.env.PORT}`)
|
logger.info(`Server started on port ${process.env.PORT}`)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/api-gateway",
|
"name": "@standardnotes/api-gateway",
|
||||||
"version": "1.75.5",
|
"version": "1.76.2",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
@@ -31,6 +31,7 @@
|
|||||||
"@standardnotes/domain-events-infra": "workspace:*",
|
"@standardnotes/domain-events-infra": "workspace:*",
|
||||||
"@standardnotes/security": "workspace:*",
|
"@standardnotes/security": "workspace:*",
|
||||||
"@standardnotes/time": "workspace:*",
|
"@standardnotes/time": "workspace:*",
|
||||||
|
"aws-xray-sdk": "^3.5.2",
|
||||||
"axios": "^1.1.3",
|
"axios": "^1.1.3",
|
||||||
"cors": "2.8.5",
|
"cors": "2.8.5",
|
||||||
"dotenv": "^16.0.1",
|
"dotenv": "^16.0.1",
|
||||||
|
|||||||
@@ -3,6 +3,95 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.150.9](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.150.8...@standardnotes/auth-server@1.150.9) (2023-10-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
## [1.150.8](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.150.7...@standardnotes/auth-server@1.150.8) (2023-10-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
## [1.150.7](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.150.6...@standardnotes/auth-server@1.150.7) (2023-10-04)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* identifying services in workers ([eab78b3](https://github.com/standardnotes/server/commit/eab78b3a95ec82cb779d069d172169bfa92368c9))
|
||||||
|
|
||||||
|
## [1.150.6](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.150.5...@standardnotes/auth-server@1.150.6) (2023-10-04)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **auth:** disable users from registering to MongoDB ([d4579ce](https://github.com/standardnotes/server/commit/d4579ce21ed34ba433deb1fe2ff25c073fbe9622))
|
||||||
|
|
||||||
|
## [1.150.5](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.150.4...@standardnotes/auth-server@1.150.5) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
## [1.150.4](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.150.3...@standardnotes/auth-server@1.150.4) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
## [1.150.3](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.150.2...@standardnotes/auth-server@1.150.3) (2023-10-04)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **auth:** remove ec2 plugin from worker ([0281724](https://github.com/standardnotes/server/commit/02817241965db06cc02e9cca1d068446db0dee4e))
|
||||||
|
|
||||||
|
## [1.150.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.150.1...@standardnotes/auth-server@1.150.2) (2023-10-04)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **auth:** remove ec2 plugin ([373cfad](https://github.com/standardnotes/server/commit/373cfad1f7c26d3a0ec2a69e720bbce535170359))
|
||||||
|
|
||||||
|
## [1.150.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.150.0...@standardnotes/auth-server@1.150.1) (2023-10-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
# [1.150.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.149.1...@standardnotes/auth-server@1.150.0) (2023-10-03)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add xray segment tracing on auth-worker ([b1b244a](https://github.com/standardnotes/server/commit/b1b244a2cf1e17ddf67fc9b238b4b25a1bc5a190))
|
||||||
|
|
||||||
|
## [1.149.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.149.0...@standardnotes/auth-server@1.149.1) (2023-10-02)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **auth:** enable xray only for server ([71e2a41](https://github.com/standardnotes/server/commit/71e2a4187e8f79b2a3055f502310ed0b6a6d82ea))
|
||||||
|
|
||||||
|
# [1.149.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.148.2...@standardnotes/auth-server@1.149.0) (2023-10-02)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **auth:** add aws xray ecs and ec2 plugins ([3838358](https://github.com/standardnotes/server/commit/383835808165aba58d15e79f03b5ba4e1c899f4c))
|
||||||
|
* **auth:** prevent from loop disabling of email settings ([#858](https://github.com/standardnotes/server/issues/858)) ([bd71422](https://github.com/standardnotes/server/commit/bd71422fabc4b5b47cca6dd071e3332943adc81d))
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **auth:** introduce AWS X-Ray SDK ([#859](https://github.com/standardnotes/server/issues/859)) ([1a388f0](https://github.com/standardnotes/server/commit/1a388f00c3897d1ebb1411793cfb23c3d305ac2e))
|
||||||
|
|
||||||
|
## [1.148.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.148.1...@standardnotes/auth-server@1.148.2) (2023-09-29)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **auth:** increase ttl for in progress duration of transitions ([681e037](https://github.com/standardnotes/server/commit/681e0378ae6b97c838b0b34ccc630194b304b81a))
|
||||||
|
|
||||||
|
## [1.148.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.148.0...@standardnotes/auth-server@1.148.1) (2023-09-29)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **auth:** disable transitions retriggering if they are in progress ([5ef6c5c](https://github.com/standardnotes/server/commit/5ef6c5c14a9f7a558de7ac9ff0ab99a5f831c127))
|
||||||
|
|
||||||
|
# [1.148.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.147.1...@standardnotes/auth-server@1.148.0) (2023-09-28)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* block file operations during transition ([#856](https://github.com/standardnotes/server/issues/856)) ([676cf36](https://github.com/standardnotes/server/commit/676cf36f8d769aa433880b2800f0457d06fbbf14))
|
||||||
|
|
||||||
|
## [1.147.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.147.0...@standardnotes/auth-server@1.147.1) (2023-09-27)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
# [1.147.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.146.4...@standardnotes/auth-server@1.147.0) (2023-09-26)
|
# [1.147.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.146.4...@standardnotes/auth-server@1.147.0) (2023-09-26)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -24,11 +24,13 @@ import { urlencoded, json, Request, Response, NextFunction } from 'express'
|
|||||||
import * as winston from 'winston'
|
import * as winston from 'winston'
|
||||||
import * as dayjs from 'dayjs'
|
import * as dayjs from 'dayjs'
|
||||||
import * as utc from 'dayjs/plugin/utc'
|
import * as utc from 'dayjs/plugin/utc'
|
||||||
|
import * as AWSXRay from 'aws-xray-sdk'
|
||||||
|
|
||||||
import { InversifyExpressServer } from 'inversify-express-utils'
|
import { InversifyExpressServer } from 'inversify-express-utils'
|
||||||
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
||||||
import TYPES from '../src/Bootstrap/Types'
|
import TYPES from '../src/Bootstrap/Types'
|
||||||
import { Env } from '../src/Bootstrap/Env'
|
import { Env } from '../src/Bootstrap/Env'
|
||||||
|
import { ServiceIdentifier } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
const container = new ContainerConfigLoader()
|
const container = new ContainerConfigLoader()
|
||||||
void container.load().then((container) => {
|
void container.load().then((container) => {
|
||||||
@@ -37,9 +39,20 @@ void container.load().then((container) => {
|
|||||||
const env: Env = new Env()
|
const env: Env = new Env()
|
||||||
env.load()
|
env.load()
|
||||||
|
|
||||||
|
const isConfiguredForAWSProduction =
|
||||||
|
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
|
||||||
|
|
||||||
|
if (isConfiguredForAWSProduction) {
|
||||||
|
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
|
||||||
|
}
|
||||||
|
|
||||||
const server = new InversifyExpressServer(container)
|
const server = new InversifyExpressServer(container)
|
||||||
|
|
||||||
server.setConfig((app) => {
|
server.setConfig((app) => {
|
||||||
|
if (isConfiguredForAWSProduction) {
|
||||||
|
app.use(AWSXRay.express.openSegment(ServiceIdentifier.NAMES.Auth))
|
||||||
|
}
|
||||||
|
|
||||||
app.use((_request: Request, response: Response, next: NextFunction) => {
|
app.use((_request: Request, response: Response, next: NextFunction) => {
|
||||||
response.setHeader('X-Auth-Version', container.get(TYPES.Auth_VERSION))
|
response.setHeader('X-Auth-Version', container.get(TYPES.Auth_VERSION))
|
||||||
next()
|
next()
|
||||||
@@ -66,6 +79,10 @@ void container.load().then((container) => {
|
|||||||
|
|
||||||
const serverInstance = server.build()
|
const serverInstance = server.build()
|
||||||
|
|
||||||
|
if (isConfiguredForAWSProduction) {
|
||||||
|
serverInstance.use(AWSXRay.express.closeSegment())
|
||||||
|
}
|
||||||
|
|
||||||
serverInstance.listen(env.get('PORT'))
|
serverInstance.listen(env.get('PORT'))
|
||||||
|
|
||||||
logger.info(`Server started on port ${process.env.PORT}`)
|
logger.info(`Server started on port ${process.env.PORT}`)
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ const requestTransition = async (
|
|||||||
|
|
||||||
let wasTransitionRequested = false
|
let wasTransitionRequested = false
|
||||||
|
|
||||||
if (itemsTransitionStatus?.value !== TransitionStatus.STATUSES.Verified) {
|
if (itemsTransitionStatus === null || itemsTransitionStatus.value === TransitionStatus.STATUSES.Failed) {
|
||||||
wasTransitionRequested = true
|
wasTransitionRequested = true
|
||||||
await transitionStatusRepository.remove(user.uuid, 'items')
|
await transitionStatusRepository.remove(user.uuid, 'items')
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ const requestTransition = async (
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (revisionsTransitionStatus?.value !== TransitionStatus.STATUSES.Verified) {
|
if (revisionsTransitionStatus === null || revisionsTransitionStatus.value === TransitionStatus.STATUSES.Failed) {
|
||||||
wasTransitionRequested = true
|
wasTransitionRequested = true
|
||||||
await transitionStatusRepository.remove(user.uuid, 'revisions')
|
await transitionStatusRepository.remove(user.uuid, 'revisions')
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { Env } from '../src/Bootstrap/Env'
|
|||||||
import { DomainEventSubscriberFactoryInterface } from '@standardnotes/domain-events'
|
import { DomainEventSubscriberFactoryInterface } from '@standardnotes/domain-events'
|
||||||
import * as dayjs from 'dayjs'
|
import * as dayjs from 'dayjs'
|
||||||
import * as utc from 'dayjs/plugin/utc'
|
import * as utc from 'dayjs/plugin/utc'
|
||||||
|
import * as AWSXRay from 'aws-xray-sdk'
|
||||||
|
|
||||||
const container = new ContainerConfigLoader('worker')
|
const container = new ContainerConfigLoader('worker')
|
||||||
void container.load().then((container) => {
|
void container.load().then((container) => {
|
||||||
@@ -16,6 +17,14 @@ void container.load().then((container) => {
|
|||||||
const env: Env = new Env()
|
const env: Env = new Env()
|
||||||
env.load()
|
env.load()
|
||||||
|
|
||||||
|
const isConfiguredForAWSProduction =
|
||||||
|
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
|
||||||
|
|
||||||
|
if (isConfiguredForAWSProduction) {
|
||||||
|
AWSXRay.enableManualMode()
|
||||||
|
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
|
||||||
|
}
|
||||||
|
|
||||||
const logger: Logger = container.get(TYPES.Auth_Logger)
|
const logger: Logger = container.get(TYPES.Auth_Logger)
|
||||||
|
|
||||||
logger.info('Starting worker...')
|
logger.info('Starting worker...')
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/auth-server",
|
"name": "@standardnotes/auth-server",
|
||||||
"version": "1.147.0",
|
"version": "1.150.9",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
@@ -54,6 +54,7 @@
|
|||||||
"@standardnotes/sncrypto-common": "^1.13.4",
|
"@standardnotes/sncrypto-common": "^1.13.4",
|
||||||
"@standardnotes/sncrypto-node": "workspace:*",
|
"@standardnotes/sncrypto-node": "workspace:*",
|
||||||
"@standardnotes/time": "workspace:*",
|
"@standardnotes/time": "workspace:*",
|
||||||
|
"aws-xray-sdk": "^3.5.2",
|
||||||
"axios": "^1.1.3",
|
"axios": "^1.1.3",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"cors": "2.8.5",
|
"cors": "2.8.5",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import * as winston from 'winston'
|
import * as winston from 'winston'
|
||||||
import Redis from 'ioredis'
|
import Redis from 'ioredis'
|
||||||
|
import { captureAWSv3Client } from 'aws-xray-sdk'
|
||||||
import { SNSClient, SNSClientConfig } from '@aws-sdk/client-sns'
|
import { SNSClient, SNSClientConfig } from '@aws-sdk/client-sns'
|
||||||
import { SQSClient, SQSClientConfig } from '@aws-sdk/client-sqs'
|
import { SQSClient, SQSClientConfig } from '@aws-sdk/client-sqs'
|
||||||
import { Container } from 'inversify'
|
import { Container } from 'inversify'
|
||||||
@@ -92,7 +93,7 @@ import {
|
|||||||
SNSDomainEventPublisher,
|
SNSDomainEventPublisher,
|
||||||
SQSDomainEventSubscriberFactory,
|
SQSDomainEventSubscriberFactory,
|
||||||
SQSEventMessageHandler,
|
SQSEventMessageHandler,
|
||||||
SQSNewRelicEventMessageHandler,
|
SQSXRayEventMessageHandler,
|
||||||
} from '@standardnotes/domain-events-infra'
|
} from '@standardnotes/domain-events-infra'
|
||||||
import { GetUserSubscription } from '../Domain/UseCase/GetUserSubscription/GetUserSubscription'
|
import { GetUserSubscription } from '../Domain/UseCase/GetUserSubscription/GetUserSubscription'
|
||||||
import { ChangeCredentials } from '../Domain/UseCase/ChangeCredentials/ChangeCredentials'
|
import { ChangeCredentials } from '../Domain/UseCase/ChangeCredentials/ChangeCredentials'
|
||||||
@@ -189,6 +190,7 @@ import {
|
|||||||
ControllerContainer,
|
ControllerContainer,
|
||||||
ControllerContainerInterface,
|
ControllerContainerInterface,
|
||||||
MapperInterface,
|
MapperInterface,
|
||||||
|
ServiceIdentifier,
|
||||||
SharedVaultUser,
|
SharedVaultUser,
|
||||||
} from '@standardnotes/domain-core'
|
} from '@standardnotes/domain-core'
|
||||||
import { SessionTracePersistenceMapper } from '../Mapping/SessionTracePersistenceMapper'
|
import { SessionTracePersistenceMapper } from '../Mapping/SessionTracePersistenceMapper'
|
||||||
@@ -273,6 +275,7 @@ import { UserAddedToSharedVaultEventHandler } from '../Domain/Handler/UserAddedT
|
|||||||
import { UserRemovedFromSharedVaultEventHandler } from '../Domain/Handler/UserRemovedFromSharedVaultEventHandler'
|
import { UserRemovedFromSharedVaultEventHandler } from '../Domain/Handler/UserRemovedFromSharedVaultEventHandler'
|
||||||
import { DesignateSurvivor } from '../Domain/UseCase/DesignateSurvivor/DesignateSurvivor'
|
import { DesignateSurvivor } from '../Domain/UseCase/DesignateSurvivor/DesignateSurvivor'
|
||||||
import { UserDesignatedAsSurvivorInSharedVaultEventHandler } from '../Domain/Handler/UserDesignatedAsSurvivorInSharedVaultEventHandler'
|
import { UserDesignatedAsSurvivorInSharedVaultEventHandler } from '../Domain/Handler/UserDesignatedAsSurvivorInSharedVaultEventHandler'
|
||||||
|
import { DisableEmailSettingBasedOnEmailSubscription } from '../Domain/UseCase/DisableEmailSettingBasedOnEmailSubscription/DisableEmailSettingBasedOnEmailSubscription'
|
||||||
|
|
||||||
export class ContainerConfigLoader {
|
export class ContainerConfigLoader {
|
||||||
constructor(private mode: 'server' | 'worker' = 'server') {}
|
constructor(private mode: 'server' | 'worker' = 'server') {}
|
||||||
@@ -319,6 +322,8 @@ export class ContainerConfigLoader {
|
|||||||
logger.debug('Database initialized')
|
logger.debug('Database initialized')
|
||||||
|
|
||||||
const isConfiguredForHomeServer = env.get('MODE', true) === 'home-server'
|
const isConfiguredForHomeServer = env.get('MODE', true) === 'home-server'
|
||||||
|
const isConfiguredForSelfHosting = env.get('MODE', true) === 'self-hosted'
|
||||||
|
const isConfiguredForAWSProduction = !isConfiguredForHomeServer && !isConfiguredForSelfHosting
|
||||||
const isConfiguredForInMemoryCache = env.get('CACHE_TYPE', true) === 'memory'
|
const isConfiguredForInMemoryCache = env.get('CACHE_TYPE', true) === 'memory'
|
||||||
|
|
||||||
if (!isConfiguredForInMemoryCache) {
|
if (!isConfiguredForInMemoryCache) {
|
||||||
@@ -349,7 +354,11 @@ export class ContainerConfigLoader {
|
|||||||
secretAccessKey: env.get('SNS_SECRET_ACCESS_KEY', true),
|
secretAccessKey: env.get('SNS_SECRET_ACCESS_KEY', true),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
container.bind<SNSClient>(TYPES.Auth_SNS).toConstantValue(new SNSClient(snsConfig))
|
let snsClient = new SNSClient(snsConfig)
|
||||||
|
if (isConfiguredForAWSProduction) {
|
||||||
|
snsClient = captureAWSv3Client(snsClient)
|
||||||
|
}
|
||||||
|
container.bind<SNSClient>(TYPES.Auth_SNS).toConstantValue(snsClient)
|
||||||
|
|
||||||
const sqsConfig: SQSClientConfig = {
|
const sqsConfig: SQSClientConfig = {
|
||||||
region: env.get('SQS_AWS_REGION', true),
|
region: env.get('SQS_AWS_REGION', true),
|
||||||
@@ -363,13 +372,17 @@ export class ContainerConfigLoader {
|
|||||||
secretAccessKey: env.get('SQS_SECRET_ACCESS_KEY', true),
|
secretAccessKey: env.get('SQS_SECRET_ACCESS_KEY', true),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
container.bind<SQSClient>(TYPES.Auth_SQS).toConstantValue(new SQSClient(sqsConfig))
|
let sqsClient = new SQSClient(sqsConfig)
|
||||||
|
if (isConfiguredForAWSProduction) {
|
||||||
|
sqsClient = captureAWSv3Client(sqsClient)
|
||||||
|
}
|
||||||
|
container.bind<SQSClient>(TYPES.Auth_SQS).toConstantValue(sqsClient)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mapping
|
// Mapping
|
||||||
container
|
container
|
||||||
.bind<MapperInterface<SessionTrace, TypeORMSessionTrace>>(TYPES.Auth_SessionTracePersistenceMapper)
|
.bind<MapperInterface<SessionTrace, TypeORMSessionTrace>>(TYPES.Auth_SessionTracePersistenceMapper)
|
||||||
.toConstantValue(new SessionTracePersistenceMapper())
|
.toConstantValue(new SessionTracePersistenceMapper(container.get<TimerInterface>(TYPES.Auth_Timer)))
|
||||||
container
|
container
|
||||||
.bind<MapperInterface<Authenticator, TypeORMAuthenticator>>(TYPES.Auth_AuthenticatorPersistenceMapper)
|
.bind<MapperInterface<Authenticator, TypeORMAuthenticator>>(TYPES.Auth_AuthenticatorPersistenceMapper)
|
||||||
.toConstantValue(new AuthenticatorPersistenceMapper())
|
.toConstantValue(new AuthenticatorPersistenceMapper())
|
||||||
@@ -458,8 +471,9 @@ export class ContainerConfigLoader {
|
|||||||
.bind<SessionTraceRepositoryInterface>(TYPES.Auth_SessionTraceRepository)
|
.bind<SessionTraceRepositoryInterface>(TYPES.Auth_SessionTraceRepository)
|
||||||
.toConstantValue(
|
.toConstantValue(
|
||||||
new TypeORMSessionTraceRepository(
|
new TypeORMSessionTraceRepository(
|
||||||
container.get(TYPES.Auth_ORMSessionTraceRepository),
|
container.get<Repository<TypeORMSessionTrace>>(TYPES.Auth_ORMSessionTraceRepository),
|
||||||
container.get(TYPES.Auth_SessionTracePersistenceMapper),
|
container.get<MapperInterface<SessionTrace, TypeORMSessionTrace>>(TYPES.Auth_SessionTracePersistenceMapper),
|
||||||
|
container.get<TimerInterface>(TYPES.Auth_Timer),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
container
|
container
|
||||||
@@ -497,20 +511,6 @@ export class ContainerConfigLoader {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Middleware
|
|
||||||
container.bind<SessionMiddleware>(TYPES.Auth_SessionMiddleware).to(SessionMiddleware)
|
|
||||||
container.bind<LockMiddleware>(TYPES.Auth_LockMiddleware).to(LockMiddleware)
|
|
||||||
container
|
|
||||||
.bind<RequiredCrossServiceTokenMiddleware>(TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
|
||||||
.to(RequiredCrossServiceTokenMiddleware)
|
|
||||||
container
|
|
||||||
.bind<OptionalCrossServiceTokenMiddleware>(TYPES.Auth_OptionalCrossServiceTokenMiddleware)
|
|
||||||
.to(OptionalCrossServiceTokenMiddleware)
|
|
||||||
container
|
|
||||||
.bind<ApiGatewayOfflineAuthMiddleware>(TYPES.Auth_ApiGatewayOfflineAuthMiddleware)
|
|
||||||
.to(ApiGatewayOfflineAuthMiddleware)
|
|
||||||
container.bind<OfflineUserAuthMiddleware>(TYPES.Auth_OfflineUserAuthMiddleware).to(OfflineUserAuthMiddleware)
|
|
||||||
|
|
||||||
// Projectors
|
// Projectors
|
||||||
container.bind<SessionProjector>(TYPES.Auth_SessionProjector).to(SessionProjector)
|
container.bind<SessionProjector>(TYPES.Auth_SessionProjector).to(SessionProjector)
|
||||||
container.bind<UserProjector>(TYPES.Auth_UserProjector).to(UserProjector)
|
container.bind<UserProjector>(TYPES.Auth_UserProjector).to(UserProjector)
|
||||||
@@ -739,6 +739,32 @@ export class ContainerConfigLoader {
|
|||||||
: new SNSDomainEventPublisher(container.get(TYPES.Auth_SNS), container.get(TYPES.Auth_SNS_TOPIC_ARN)),
|
: new SNSDomainEventPublisher(container.get(TYPES.Auth_SNS), container.get(TYPES.Auth_SNS_TOPIC_ARN)),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Middleware
|
||||||
|
container.bind<SessionMiddleware>(TYPES.Auth_SessionMiddleware).to(SessionMiddleware)
|
||||||
|
container.bind<LockMiddleware>(TYPES.Auth_LockMiddleware).to(LockMiddleware)
|
||||||
|
container
|
||||||
|
.bind<RequiredCrossServiceTokenMiddleware>(TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
|
.toConstantValue(
|
||||||
|
new RequiredCrossServiceTokenMiddleware(
|
||||||
|
container.get<TokenDecoderInterface<CrossServiceTokenData>>(TYPES.Auth_CrossServiceTokenDecoder),
|
||||||
|
isConfiguredForAWSProduction && this.mode === 'server',
|
||||||
|
container.get<winston.Logger>(TYPES.Auth_Logger),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
container
|
||||||
|
.bind<OptionalCrossServiceTokenMiddleware>(TYPES.Auth_OptionalCrossServiceTokenMiddleware)
|
||||||
|
.toConstantValue(
|
||||||
|
new OptionalCrossServiceTokenMiddleware(
|
||||||
|
container.get<TokenDecoderInterface<CrossServiceTokenData>>(TYPES.Auth_CrossServiceTokenDecoder),
|
||||||
|
isConfiguredForAWSProduction && this.mode === 'server',
|
||||||
|
container.get<winston.Logger>(TYPES.Auth_Logger),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
container
|
||||||
|
.bind<ApiGatewayOfflineAuthMiddleware>(TYPES.Auth_ApiGatewayOfflineAuthMiddleware)
|
||||||
|
.to(ApiGatewayOfflineAuthMiddleware)
|
||||||
|
container.bind<OfflineUserAuthMiddleware>(TYPES.Auth_OfflineUserAuthMiddleware).to(OfflineUserAuthMiddleware)
|
||||||
|
|
||||||
// use cases
|
// use cases
|
||||||
container
|
container
|
||||||
.bind<TraceSession>(TYPES.Auth_TraceSession)
|
.bind<TraceSession>(TYPES.Auth_TraceSession)
|
||||||
@@ -964,6 +990,15 @@ export class ContainerConfigLoader {
|
|||||||
container.get<TimerInterface>(TYPES.Auth_Timer),
|
container.get<TimerInterface>(TYPES.Auth_Timer),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
container
|
||||||
|
.bind<DisableEmailSettingBasedOnEmailSubscription>(TYPES.Auth_DisableEmailSettingBasedOnEmailSubscription)
|
||||||
|
.toConstantValue(
|
||||||
|
new DisableEmailSettingBasedOnEmailSubscription(
|
||||||
|
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
|
||||||
|
container.get<SettingRepositoryInterface>(TYPES.Auth_SettingRepository),
|
||||||
|
container.get<SettingFactoryInterface>(TYPES.Auth_SettingFactory),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
// Controller
|
// Controller
|
||||||
container
|
container
|
||||||
@@ -1011,7 +1046,6 @@ export class ContainerConfigLoader {
|
|||||||
container.get<SessionRepositoryInterface>(TYPES.Auth_SessionRepository),
|
container.get<SessionRepositoryInterface>(TYPES.Auth_SessionRepository),
|
||||||
container.get<EphemeralSessionRepositoryInterface>(TYPES.Auth_EphemeralSessionRepository),
|
container.get<EphemeralSessionRepositoryInterface>(TYPES.Auth_EphemeralSessionRepository),
|
||||||
container.get<RevokedSessionRepositoryInterface>(TYPES.Auth_RevokedSessionRepository),
|
container.get<RevokedSessionRepositoryInterface>(TYPES.Auth_RevokedSessionRepository),
|
||||||
container.get<RemoveSharedVaultUser>(TYPES.Auth_RemoveSharedVaultUser),
|
|
||||||
container.get<winston.Logger>(TYPES.Auth_Logger),
|
container.get<winston.Logger>(TYPES.Auth_Logger),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -1102,8 +1136,10 @@ export class ContainerConfigLoader {
|
|||||||
.bind<EmailSubscriptionUnsubscribedEventHandler>(TYPES.Auth_EmailSubscriptionUnsubscribedEventHandler)
|
.bind<EmailSubscriptionUnsubscribedEventHandler>(TYPES.Auth_EmailSubscriptionUnsubscribedEventHandler)
|
||||||
.toConstantValue(
|
.toConstantValue(
|
||||||
new EmailSubscriptionUnsubscribedEventHandler(
|
new EmailSubscriptionUnsubscribedEventHandler(
|
||||||
container.get(TYPES.Auth_UserRepository),
|
container.get<DisableEmailSettingBasedOnEmailSubscription>(
|
||||||
container.get(TYPES.Auth_SettingService),
|
TYPES.Auth_DisableEmailSettingBasedOnEmailSubscription,
|
||||||
|
),
|
||||||
|
container.get<winston.Logger>(TYPES.Auth_Logger),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
container
|
container
|
||||||
@@ -1201,8 +1237,12 @@ export class ContainerConfigLoader {
|
|||||||
container
|
container
|
||||||
.bind<DomainEventMessageHandlerInterface>(TYPES.Auth_DomainEventMessageHandler)
|
.bind<DomainEventMessageHandlerInterface>(TYPES.Auth_DomainEventMessageHandler)
|
||||||
.toConstantValue(
|
.toConstantValue(
|
||||||
env.get('NEW_RELIC_ENABLED', true) === 'true'
|
isConfiguredForAWSProduction
|
||||||
? new SQSNewRelicEventMessageHandler(eventHandlers, container.get(TYPES.Auth_Logger))
|
? new SQSXRayEventMessageHandler(
|
||||||
|
ServiceIdentifier.NAMES.AuthWorker,
|
||||||
|
eventHandlers,
|
||||||
|
container.get(TYPES.Auth_Logger),
|
||||||
|
)
|
||||||
: new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Auth_Logger)),
|
: new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Auth_Logger)),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -161,6 +161,7 @@ const TYPES = {
|
|||||||
Auth_AddSharedVaultUser: Symbol.for('Auth_AddSharedVaultUser'),
|
Auth_AddSharedVaultUser: Symbol.for('Auth_AddSharedVaultUser'),
|
||||||
Auth_RemoveSharedVaultUser: Symbol.for('Auth_RemoveSharedVaultUser'),
|
Auth_RemoveSharedVaultUser: Symbol.for('Auth_RemoveSharedVaultUser'),
|
||||||
Auth_DesignateSurvivor: Symbol.for('Auth_DesignateSurvivor'),
|
Auth_DesignateSurvivor: Symbol.for('Auth_DesignateSurvivor'),
|
||||||
|
Auth_DisableEmailSettingBasedOnEmailSubscription: Symbol.for('Auth_DisableEmailSettingBasedOnEmailSubscription'),
|
||||||
// Handlers
|
// Handlers
|
||||||
Auth_UserRegisteredEventHandler: Symbol.for('Auth_UserRegisteredEventHandler'),
|
Auth_UserRegisteredEventHandler: Symbol.for('Auth_UserRegisteredEventHandler'),
|
||||||
Auth_AccountDeletionRequestedEventHandler: Symbol.for('Auth_AccountDeletionRequestedEventHandler'),
|
Auth_AccountDeletionRequestedEventHandler: Symbol.for('Auth_AccountDeletionRequestedEventHandler'),
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { EphemeralSessionRepositoryInterface } from '../Session/EphemeralSession
|
|||||||
import { RevokedSessionRepositoryInterface } from '../Session/RevokedSessionRepositoryInterface'
|
import { RevokedSessionRepositoryInterface } from '../Session/RevokedSessionRepositoryInterface'
|
||||||
import { SessionRepositoryInterface } from '../Session/SessionRepositoryInterface'
|
import { SessionRepositoryInterface } from '../Session/SessionRepositoryInterface'
|
||||||
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
|
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
|
||||||
import { RemoveSharedVaultUser } from '../UseCase/RemoveSharedVaultUser/RemoveSharedVaultUser'
|
|
||||||
|
|
||||||
export class AccountDeletionRequestedEventHandler implements DomainEventHandlerInterface {
|
export class AccountDeletionRequestedEventHandler implements DomainEventHandlerInterface {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -14,7 +13,6 @@ export class AccountDeletionRequestedEventHandler implements DomainEventHandlerI
|
|||||||
private sessionRepository: SessionRepositoryInterface,
|
private sessionRepository: SessionRepositoryInterface,
|
||||||
private ephemeralSessionRepository: EphemeralSessionRepositoryInterface,
|
private ephemeralSessionRepository: EphemeralSessionRepositoryInterface,
|
||||||
private revokedSessionRepository: RevokedSessionRepositoryInterface,
|
private revokedSessionRepository: RevokedSessionRepositoryInterface,
|
||||||
private removeSharedVaultUser: RemoveSharedVaultUser,
|
|
||||||
private logger: Logger,
|
private logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@@ -37,13 +35,6 @@ export class AccountDeletionRequestedEventHandler implements DomainEventHandlerI
|
|||||||
|
|
||||||
await this.removeSessions(userUuid.value)
|
await this.removeSessions(userUuid.value)
|
||||||
|
|
||||||
const result = await this.removeSharedVaultUser.execute({
|
|
||||||
userUuid: userUuid.value,
|
|
||||||
})
|
|
||||||
if (result.isFailed()) {
|
|
||||||
this.logger.error(`Could not remove shared vault user: ${result.getError()}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.userRepository.remove(user)
|
await this.userRepository.remove(user)
|
||||||
|
|
||||||
this.logger.info(`Finished account cleanup for user: ${userUuid.value}`)
|
this.logger.info(`Finished account cleanup for user: ${userUuid.value}`)
|
||||||
|
|||||||
@@ -1,117 +0,0 @@
|
|||||||
import { EmailLevel } from '@standardnotes/domain-core'
|
|
||||||
import { EmailSubscriptionUnsubscribedEvent } from '@standardnotes/domain-events'
|
|
||||||
|
|
||||||
import { SettingServiceInterface } from '../Setting/SettingServiceInterface'
|
|
||||||
import { User } from '../User/User'
|
|
||||||
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
|
|
||||||
import { EmailSubscriptionUnsubscribedEventHandler } from './EmailSubscriptionUnsubscribedEventHandler'
|
|
||||||
|
|
||||||
describe('EmailSubscriptionUnsubscribedEventHandler', () => {
|
|
||||||
let userRepository: UserRepositoryInterface
|
|
||||||
let settingsService: SettingServiceInterface
|
|
||||||
let event: EmailSubscriptionUnsubscribedEvent
|
|
||||||
|
|
||||||
const createHandler = () => new EmailSubscriptionUnsubscribedEventHandler(userRepository, settingsService)
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
userRepository = {} as jest.Mocked<UserRepositoryInterface>
|
|
||||||
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue({} as jest.Mocked<User>)
|
|
||||||
|
|
||||||
settingsService = {} as jest.Mocked<SettingServiceInterface>
|
|
||||||
settingsService.createOrReplace = jest.fn()
|
|
||||||
|
|
||||||
event = {
|
|
||||||
payload: {
|
|
||||||
userEmail: 'test@test.te',
|
|
||||||
level: EmailLevel.LEVELS.Marketing,
|
|
||||||
},
|
|
||||||
} as jest.Mocked<EmailSubscriptionUnsubscribedEvent>
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should not do anything if username is invalid', async () => {
|
|
||||||
event.payload.userEmail = ''
|
|
||||||
|
|
||||||
await createHandler().handle(event)
|
|
||||||
|
|
||||||
expect(settingsService.createOrReplace).not.toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should not do anything if user is not found', async () => {
|
|
||||||
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue(null)
|
|
||||||
|
|
||||||
await createHandler().handle(event)
|
|
||||||
|
|
||||||
expect(settingsService.createOrReplace).not.toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should update user marketing email settings', async () => {
|
|
||||||
await createHandler().handle(event)
|
|
||||||
|
|
||||||
expect(settingsService.createOrReplace).toHaveBeenCalledWith({
|
|
||||||
user: {},
|
|
||||||
props: {
|
|
||||||
name: 'MUTE_MARKETING_EMAILS',
|
|
||||||
unencryptedValue: 'muted',
|
|
||||||
sensitive: false,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should update user sign in email settings', async () => {
|
|
||||||
event.payload.level = EmailLevel.LEVELS.SignIn
|
|
||||||
|
|
||||||
await createHandler().handle(event)
|
|
||||||
|
|
||||||
expect(settingsService.createOrReplace).toHaveBeenCalledWith({
|
|
||||||
user: {},
|
|
||||||
props: {
|
|
||||||
name: 'MUTE_SIGN_IN_EMAILS',
|
|
||||||
unencryptedValue: 'muted',
|
|
||||||
sensitive: false,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should update user email backup email settings', async () => {
|
|
||||||
event.payload.level = EmailLevel.LEVELS.FailedEmailBackup
|
|
||||||
|
|
||||||
await createHandler().handle(event)
|
|
||||||
|
|
||||||
expect(settingsService.createOrReplace).toHaveBeenCalledWith({
|
|
||||||
user: {},
|
|
||||||
props: {
|
|
||||||
name: 'MUTE_FAILED_BACKUPS_EMAILS',
|
|
||||||
unencryptedValue: 'muted',
|
|
||||||
sensitive: false,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should update user email backup email settings', async () => {
|
|
||||||
event.payload.level = EmailLevel.LEVELS.FailedCloudBackup
|
|
||||||
|
|
||||||
await createHandler().handle(event)
|
|
||||||
|
|
||||||
expect(settingsService.createOrReplace).toHaveBeenCalledWith({
|
|
||||||
user: {},
|
|
||||||
props: {
|
|
||||||
name: 'MUTE_FAILED_CLOUD_BACKUPS_EMAILS',
|
|
||||||
unencryptedValue: 'muted',
|
|
||||||
sensitive: false,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should throw error for unrecognized level', async () => {
|
|
||||||
event.payload.level = 'foobar'
|
|
||||||
|
|
||||||
let caughtError = null
|
|
||||||
try {
|
|
||||||
await createHandler().handle(event)
|
|
||||||
} catch (error) {
|
|
||||||
caughtError = error
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(caughtError).not.toBeNull()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,50 +1,21 @@
|
|||||||
import { EmailLevel, Username } from '@standardnotes/domain-core'
|
|
||||||
import { DomainEventHandlerInterface, EmailSubscriptionUnsubscribedEvent } from '@standardnotes/domain-events'
|
import { DomainEventHandlerInterface, EmailSubscriptionUnsubscribedEvent } from '@standardnotes/domain-events'
|
||||||
import { SettingName } from '@standardnotes/settings'
|
import { Logger } from 'winston'
|
||||||
|
import { DisableEmailSettingBasedOnEmailSubscription } from '../UseCase/DisableEmailSettingBasedOnEmailSubscription/DisableEmailSettingBasedOnEmailSubscription'
|
||||||
import { SettingServiceInterface } from '../Setting/SettingServiceInterface'
|
|
||||||
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
|
|
||||||
|
|
||||||
export class EmailSubscriptionUnsubscribedEventHandler implements DomainEventHandlerInterface {
|
export class EmailSubscriptionUnsubscribedEventHandler implements DomainEventHandlerInterface {
|
||||||
constructor(
|
constructor(
|
||||||
private userRepository: UserRepositoryInterface,
|
private disableEmailSettingBasedOnEmailSubscription: DisableEmailSettingBasedOnEmailSubscription,
|
||||||
private settingsService: SettingServiceInterface,
|
private logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async handle(event: EmailSubscriptionUnsubscribedEvent): Promise<void> {
|
async handle(event: EmailSubscriptionUnsubscribedEvent): Promise<void> {
|
||||||
const usernameOrError = Username.create(event.payload.userEmail)
|
const result = await this.disableEmailSettingBasedOnEmailSubscription.execute({
|
||||||
if (usernameOrError.isFailed()) {
|
userEmail: event.payload.userEmail,
|
||||||
return
|
level: event.payload.level,
|
||||||
}
|
|
||||||
const username = usernameOrError.getValue()
|
|
||||||
|
|
||||||
const user = await this.userRepository.findOneByUsernameOrEmail(username)
|
|
||||||
if (user === null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.settingsService.createOrReplace({
|
|
||||||
user,
|
|
||||||
props: {
|
|
||||||
name: this.getSettingNameFromLevel(event.payload.level),
|
|
||||||
unencryptedValue: 'muted',
|
|
||||||
sensitive: false,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
private getSettingNameFromLevel(level: string): string {
|
if (result.isFailed()) {
|
||||||
switch (level) {
|
this.logger.error(`Failed to disable email setting for user ${event.payload.userEmail}: ${result.getError()}`)
|
||||||
case EmailLevel.LEVELS.FailedCloudBackup:
|
|
||||||
return SettingName.NAMES.MuteFailedCloudBackupsEmails
|
|
||||||
case EmailLevel.LEVELS.FailedEmailBackup:
|
|
||||||
return SettingName.NAMES.MuteFailedBackupsEmails
|
|
||||||
case EmailLevel.LEVELS.Marketing:
|
|
||||||
return SettingName.NAMES.MuteMarketingEmails
|
|
||||||
case EmailLevel.LEVELS.SignIn:
|
|
||||||
return SettingName.NAMES.MuteSignInEmails
|
|
||||||
default:
|
|
||||||
throw new Error(`Unknown level: ${level}`)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { SubscriptionPlanName, Uuid } from '@standardnotes/domain-core'
|
|||||||
import { SessionTrace } from './SessionTrace'
|
import { SessionTrace } from './SessionTrace'
|
||||||
|
|
||||||
export interface SessionTraceRepositoryInterface {
|
export interface SessionTraceRepositoryInterface {
|
||||||
save(sessionTrace: SessionTrace): Promise<void>
|
insert(sessionTrace: SessionTrace): Promise<void>
|
||||||
removeExpiredBefore(date: Date): Promise<void>
|
removeExpiredBefore(date: Date): Promise<void>
|
||||||
findOneByUserUuidAndDate(userUuid: Uuid, date: Date): Promise<SessionTrace | null>
|
findOneByUserUuidAndDate(userUuid: Uuid, date: Date): Promise<SessionTrace | null>
|
||||||
countByDate(date: Date): Promise<number>
|
countByDate(date: Date): Promise<number>
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
import 'reflect-metadata'
|
import 'reflect-metadata'
|
||||||
|
|
||||||
import { TokenEncoderInterface, ValetTokenData, ValetTokenOperation } from '@standardnotes/security'
|
import { TransitionStatus } from '@standardnotes/domain-core'
|
||||||
import { CreateValetToken } from './CreateValetToken'
|
|
||||||
import { TimerInterface } from '@standardnotes/time'
|
import { TimerInterface } from '@standardnotes/time'
|
||||||
|
import { TokenEncoderInterface, ValetTokenData, ValetTokenOperation } from '@standardnotes/security'
|
||||||
|
|
||||||
|
import { CreateValetToken } from './CreateValetToken'
|
||||||
import { UserSubscription } from '../../Subscription/UserSubscription'
|
import { UserSubscription } from '../../Subscription/UserSubscription'
|
||||||
import { SubscriptionSettingServiceInterface } from '../../Setting/SubscriptionSettingServiceInterface'
|
import { SubscriptionSettingServiceInterface } from '../../Setting/SubscriptionSettingServiceInterface'
|
||||||
import { User } from '../../User/User'
|
import { User } from '../../User/User'
|
||||||
import { UserSubscriptionType } from '../../Subscription/UserSubscriptionType'
|
import { UserSubscriptionType } from '../../Subscription/UserSubscriptionType'
|
||||||
import { SubscriptionSettingsAssociationServiceInterface } from '../../Setting/SubscriptionSettingsAssociationServiceInterface'
|
import { SubscriptionSettingsAssociationServiceInterface } from '../../Setting/SubscriptionSettingsAssociationServiceInterface'
|
||||||
import { UserSubscriptionServiceInterface } from '../../Subscription/UserSubscriptionServiceInterface'
|
import { UserSubscriptionServiceInterface } from '../../Subscription/UserSubscriptionServiceInterface'
|
||||||
|
import { TransitionStatusRepositoryInterface } from '../../Transition/TransitionStatusRepositoryInterface'
|
||||||
|
|
||||||
describe('CreateValetToken', () => {
|
describe('CreateValetToken', () => {
|
||||||
let tokenEncoder: TokenEncoderInterface<ValetTokenData>
|
let tokenEncoder: TokenEncoderInterface<ValetTokenData>
|
||||||
@@ -20,6 +23,7 @@ describe('CreateValetToken', () => {
|
|||||||
let regularSubscription: UserSubscription
|
let regularSubscription: UserSubscription
|
||||||
let sharedSubscription: UserSubscription
|
let sharedSubscription: UserSubscription
|
||||||
let user: User
|
let user: User
|
||||||
|
let transitionStatusRepository: TransitionStatusRepositoryInterface
|
||||||
|
|
||||||
const createUseCase = () =>
|
const createUseCase = () =>
|
||||||
new CreateValetToken(
|
new CreateValetToken(
|
||||||
@@ -29,6 +33,7 @@ describe('CreateValetToken', () => {
|
|||||||
userSubscriptionService,
|
userSubscriptionService,
|
||||||
timer,
|
timer,
|
||||||
valetTokenTTL,
|
valetTokenTTL,
|
||||||
|
transitionStatusRepository,
|
||||||
)
|
)
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -66,6 +71,11 @@ describe('CreateValetToken', () => {
|
|||||||
|
|
||||||
timer = {} as jest.Mocked<TimerInterface>
|
timer = {} as jest.Mocked<TimerInterface>
|
||||||
timer.getTimestampInMicroseconds = jest.fn().mockReturnValue(100)
|
timer.getTimestampInMicroseconds = jest.fn().mockReturnValue(100)
|
||||||
|
|
||||||
|
transitionStatusRepository = {} as jest.Mocked<TransitionStatusRepositoryInterface>
|
||||||
|
transitionStatusRepository.getStatus = jest
|
||||||
|
.fn()
|
||||||
|
.mockReturnValue(TransitionStatus.create(TransitionStatus.STATUSES.Verified).getValue())
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should create a read valet token', async () => {
|
it('should create a read valet token', async () => {
|
||||||
@@ -166,6 +176,7 @@ describe('CreateValetToken', () => {
|
|||||||
{
|
{
|
||||||
sharedSubscriptionUuid: undefined,
|
sharedSubscriptionUuid: undefined,
|
||||||
regularSubscriptionUuid: '1-2-3',
|
regularSubscriptionUuid: '1-2-3',
|
||||||
|
ongoingTransition: false,
|
||||||
permittedOperation: 'write',
|
permittedOperation: 'write',
|
||||||
permittedResources: [
|
permittedResources: [
|
||||||
{
|
{
|
||||||
@@ -206,6 +217,7 @@ describe('CreateValetToken', () => {
|
|||||||
{
|
{
|
||||||
sharedSubscriptionUuid: '2-3-4',
|
sharedSubscriptionUuid: '2-3-4',
|
||||||
regularSubscriptionUuid: '1-2-3',
|
regularSubscriptionUuid: '1-2-3',
|
||||||
|
ongoingTransition: false,
|
||||||
permittedOperation: 'write',
|
permittedOperation: 'write',
|
||||||
permittedResources: [
|
permittedResources: [
|
||||||
{
|
{
|
||||||
@@ -266,6 +278,7 @@ describe('CreateValetToken', () => {
|
|||||||
{
|
{
|
||||||
sharedSubscriptionUuid: undefined,
|
sharedSubscriptionUuid: undefined,
|
||||||
regularSubscriptionUuid: '1-2-3',
|
regularSubscriptionUuid: '1-2-3',
|
||||||
|
ongoingTransition: false,
|
||||||
permittedOperation: 'write',
|
permittedOperation: 'write',
|
||||||
permittedResources: [
|
permittedResources: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { CreateValetTokenDTO } from './CreateValetTokenDTO'
|
|||||||
import { SubscriptionSettingsAssociationServiceInterface } from '../../Setting/SubscriptionSettingsAssociationServiceInterface'
|
import { SubscriptionSettingsAssociationServiceInterface } from '../../Setting/SubscriptionSettingsAssociationServiceInterface'
|
||||||
import { UserSubscriptionServiceInterface } from '../../Subscription/UserSubscriptionServiceInterface'
|
import { UserSubscriptionServiceInterface } from '../../Subscription/UserSubscriptionServiceInterface'
|
||||||
import { CreateValetTokenPayload } from '../../ValetToken/CreateValetTokenPayload'
|
import { CreateValetTokenPayload } from '../../ValetToken/CreateValetTokenPayload'
|
||||||
|
import { TransitionStatusRepositoryInterface } from '../../Transition/TransitionStatusRepositoryInterface'
|
||||||
|
import { TransitionStatus } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class CreateValetToken implements UseCaseInterface {
|
export class CreateValetToken implements UseCaseInterface {
|
||||||
@@ -25,6 +27,8 @@ export class CreateValetToken implements UseCaseInterface {
|
|||||||
@inject(TYPES.Auth_UserSubscriptionService) private userSubscriptionService: UserSubscriptionServiceInterface,
|
@inject(TYPES.Auth_UserSubscriptionService) private userSubscriptionService: UserSubscriptionServiceInterface,
|
||||||
@inject(TYPES.Auth_Timer) private timer: TimerInterface,
|
@inject(TYPES.Auth_Timer) private timer: TimerInterface,
|
||||||
@inject(TYPES.Auth_VALET_TOKEN_TTL) private valetTokenTTL: number,
|
@inject(TYPES.Auth_VALET_TOKEN_TTL) private valetTokenTTL: number,
|
||||||
|
@inject(TYPES.Auth_TransitionStatusRepository)
|
||||||
|
private transitionStatusRepository: TransitionStatusRepositoryInterface,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async execute(dto: CreateValetTokenDTO): Promise<CreateValetTokenResponseData> {
|
async execute(dto: CreateValetTokenDTO): Promise<CreateValetTokenResponseData> {
|
||||||
@@ -83,6 +87,8 @@ export class CreateValetToken implements UseCaseInterface {
|
|||||||
sharedSubscriptionUuid = sharedSubscription.uuid
|
sharedSubscriptionUuid = sharedSubscription.uuid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const transitionStatus = await this.transitionStatusRepository.getStatus(userUuid, 'items')
|
||||||
|
|
||||||
const tokenData: ValetTokenData = {
|
const tokenData: ValetTokenData = {
|
||||||
userUuid: dto.userUuid,
|
userUuid: dto.userUuid,
|
||||||
permittedOperation: dto.operation,
|
permittedOperation: dto.operation,
|
||||||
@@ -91,6 +97,7 @@ export class CreateValetToken implements UseCaseInterface {
|
|||||||
uploadBytesLimit,
|
uploadBytesLimit,
|
||||||
sharedSubscriptionUuid,
|
sharedSubscriptionUuid,
|
||||||
regularSubscriptionUuid: regularSubscription.uuid,
|
regularSubscriptionUuid: regularSubscription.uuid,
|
||||||
|
ongoingTransition: transitionStatus?.value === TransitionStatus.STATUSES.InProgress,
|
||||||
}
|
}
|
||||||
|
|
||||||
const valetToken = this.tokenEncoder.encodeExpirableToken(tokenData, this.valetTokenTTL)
|
const valetToken = this.tokenEncoder.encodeExpirableToken(tokenData, this.valetTokenTTL)
|
||||||
|
|||||||
+96
@@ -0,0 +1,96 @@
|
|||||||
|
import { EmailLevel } from '@standardnotes/domain-core'
|
||||||
|
import { Setting } from '../../Setting/Setting'
|
||||||
|
import { SettingFactoryInterface } from '../../Setting/SettingFactoryInterface'
|
||||||
|
import { SettingRepositoryInterface } from '../../Setting/SettingRepositoryInterface'
|
||||||
|
import { User } from '../../User/User'
|
||||||
|
import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
|
||||||
|
import { DisableEmailSettingBasedOnEmailSubscription } from './DisableEmailSettingBasedOnEmailSubscription'
|
||||||
|
|
||||||
|
describe('DisableEmailSettingBasedOnEmailSubscription', () => {
|
||||||
|
let userRepository: UserRepositoryInterface
|
||||||
|
let settingRepository: SettingRepositoryInterface
|
||||||
|
let factory: SettingFactoryInterface
|
||||||
|
let user: User
|
||||||
|
|
||||||
|
const createUseCase = () =>
|
||||||
|
new DisableEmailSettingBasedOnEmailSubscription(userRepository, settingRepository, factory)
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
user = {} as jest.Mocked<User>
|
||||||
|
user.uuid = 'userUuid'
|
||||||
|
|
||||||
|
userRepository = {} as jest.Mocked<UserRepositoryInterface>
|
||||||
|
userRepository.findOneByUsernameOrEmail = jest.fn().mockResolvedValue(user)
|
||||||
|
|
||||||
|
settingRepository = {} as jest.Mocked<SettingRepositoryInterface>
|
||||||
|
settingRepository.findLastByNameAndUserUuid = jest.fn().mockResolvedValue({} as jest.Mocked<Setting>)
|
||||||
|
settingRepository.save = jest.fn()
|
||||||
|
|
||||||
|
factory = {} as jest.Mocked<SettingFactoryInterface>
|
||||||
|
factory.create = jest.fn().mockResolvedValue({} as jest.Mocked<Setting>)
|
||||||
|
factory.createReplacement = jest.fn().mockResolvedValue({} as jest.Mocked<Setting>)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fail if the username is empty', async () => {
|
||||||
|
const useCase = createUseCase()
|
||||||
|
|
||||||
|
const result = await useCase.execute({
|
||||||
|
userEmail: '',
|
||||||
|
level: EmailLevel.LEVELS.Marketing,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result.isFailed()).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fail if the user is not found', async () => {
|
||||||
|
userRepository.findOneByUsernameOrEmail = jest.fn().mockResolvedValue(null)
|
||||||
|
|
||||||
|
const useCase = createUseCase()
|
||||||
|
|
||||||
|
const result = await useCase.execute({
|
||||||
|
userEmail: 'test@test.te',
|
||||||
|
level: EmailLevel.LEVELS.Marketing,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result.isFailed()).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fail if the setting name cannot be determined', async () => {
|
||||||
|
const useCase = createUseCase()
|
||||||
|
|
||||||
|
const result = await useCase.execute({
|
||||||
|
userEmail: 'test@test.te',
|
||||||
|
level: 'invalid',
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result.isFailed()).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should create a new setting if it does not exist', async () => {
|
||||||
|
settingRepository.findLastByNameAndUserUuid = jest.fn().mockResolvedValue(null)
|
||||||
|
|
||||||
|
const useCase = createUseCase()
|
||||||
|
|
||||||
|
const result = await useCase.execute({
|
||||||
|
userEmail: 'test@test.te',
|
||||||
|
level: EmailLevel.LEVELS.Marketing,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result.isFailed()).toBeFalsy()
|
||||||
|
expect(factory.create).toHaveBeenCalled()
|
||||||
|
expect(factory.createReplacement).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should replace the setting if it exists', async () => {
|
||||||
|
const useCase = createUseCase()
|
||||||
|
|
||||||
|
const result = await useCase.execute({
|
||||||
|
userEmail: 'test@test.te',
|
||||||
|
level: EmailLevel.LEVELS.Marketing,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result.isFailed()).toBeFalsy()
|
||||||
|
expect(factory.create).not.toHaveBeenCalled()
|
||||||
|
expect(factory.createReplacement).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
+72
@@ -0,0 +1,72 @@
|
|||||||
|
import { EmailLevel, Result, UseCaseInterface, Username } from '@standardnotes/domain-core'
|
||||||
|
import { SettingName } from '@standardnotes/settings'
|
||||||
|
|
||||||
|
import { DisableEmailSettingBasedOnEmailSubscriptionDTO } from './DisableEmailSettingBasedOnEmailSubscriptionDTO'
|
||||||
|
import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
|
||||||
|
import { SettingRepositoryInterface } from '../../Setting/SettingRepositoryInterface'
|
||||||
|
import { SettingFactoryInterface } from '../../Setting/SettingFactoryInterface'
|
||||||
|
|
||||||
|
export class DisableEmailSettingBasedOnEmailSubscription implements UseCaseInterface<void> {
|
||||||
|
constructor(
|
||||||
|
private userRepository: UserRepositoryInterface,
|
||||||
|
private settingRepository: SettingRepositoryInterface,
|
||||||
|
private factory: SettingFactoryInterface,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async execute(dto: DisableEmailSettingBasedOnEmailSubscriptionDTO): Promise<Result<void>> {
|
||||||
|
const usernameOrError = Username.create(dto.userEmail)
|
||||||
|
if (usernameOrError.isFailed()) {
|
||||||
|
return Result.fail(usernameOrError.getError())
|
||||||
|
}
|
||||||
|
const username = usernameOrError.getValue()
|
||||||
|
|
||||||
|
const user = await this.userRepository.findOneByUsernameOrEmail(username)
|
||||||
|
if (user === null) {
|
||||||
|
return Result.fail(`User not found for email ${dto.userEmail}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const settingNameOrError = this.getSettingNameFromLevel(dto.level)
|
||||||
|
if (settingNameOrError.isFailed()) {
|
||||||
|
return Result.fail(settingNameOrError.getError())
|
||||||
|
}
|
||||||
|
const settingName = settingNameOrError.getValue()
|
||||||
|
|
||||||
|
let setting = await this.settingRepository.findLastByNameAndUserUuid(settingName, user.uuid)
|
||||||
|
if (!setting) {
|
||||||
|
setting = await this.factory.create(
|
||||||
|
{
|
||||||
|
name: settingName,
|
||||||
|
unencryptedValue: 'muted',
|
||||||
|
sensitive: false,
|
||||||
|
},
|
||||||
|
user,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
setting = await this.factory.createReplacement(setting, {
|
||||||
|
name: settingName,
|
||||||
|
unencryptedValue: 'muted',
|
||||||
|
sensitive: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.settingRepository.save(setting)
|
||||||
|
|
||||||
|
return Result.ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
private getSettingNameFromLevel(level: string): Result<string> {
|
||||||
|
/* istanbul ignore next */
|
||||||
|
switch (level) {
|
||||||
|
case EmailLevel.LEVELS.FailedCloudBackup:
|
||||||
|
return Result.ok(SettingName.NAMES.MuteFailedCloudBackupsEmails)
|
||||||
|
case EmailLevel.LEVELS.FailedEmailBackup:
|
||||||
|
return Result.ok(SettingName.NAMES.MuteFailedBackupsEmails)
|
||||||
|
case EmailLevel.LEVELS.Marketing:
|
||||||
|
return Result.ok(SettingName.NAMES.MuteMarketingEmails)
|
||||||
|
case EmailLevel.LEVELS.SignIn:
|
||||||
|
return Result.ok(SettingName.NAMES.MuteSignInEmails)
|
||||||
|
default:
|
||||||
|
return Result.fail(`Unknown level: ${level}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
export interface DisableEmailSettingBasedOnEmailSubscriptionDTO {
|
||||||
|
userEmail: string
|
||||||
|
level: string
|
||||||
|
}
|
||||||
@@ -84,14 +84,11 @@ describe('Register', () => {
|
|||||||
expect(settingService.applyDefaultSettingsUponRegistration).toHaveBeenCalled()
|
expect(settingService.applyDefaultSettingsUponRegistration).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should register a new user with default role and transition role', async () => {
|
it('should register a new user with default set of roles', async () => {
|
||||||
const role = new Role()
|
const role = new Role()
|
||||||
role.name = RoleName.NAMES.CoreUser
|
role.name = RoleName.NAMES.CoreUser
|
||||||
|
|
||||||
const transitionRole = new Role()
|
roleRepository.findOneByName = jest.fn().mockReturnValueOnce(role)
|
||||||
transitionRole.name = RoleName.NAMES.TransitionUser
|
|
||||||
|
|
||||||
roleRepository.findOneByName = jest.fn().mockReturnValueOnce(role).mockReturnValueOnce(transitionRole)
|
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await createUseCase().execute({
|
await createUseCase().execute({
|
||||||
@@ -120,7 +117,7 @@ describe('Register', () => {
|
|||||||
version: '004',
|
version: '004',
|
||||||
createdAt: new Date(1),
|
createdAt: new Date(1),
|
||||||
updatedAt: new Date(1),
|
updatedAt: new Date(1),
|
||||||
roles: Promise.resolve([role, transitionRole]),
|
roles: Promise.resolve([role]),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -77,10 +77,6 @@ export class Register implements UseCaseInterface {
|
|||||||
if (defaultRole) {
|
if (defaultRole) {
|
||||||
roles.push(defaultRole)
|
roles.push(defaultRole)
|
||||||
}
|
}
|
||||||
const transitionRole = await this.roleRepository.findOneByName(RoleName.NAMES.TransitionUser)
|
|
||||||
if (transitionRole) {
|
|
||||||
roles.push(transitionRole)
|
|
||||||
}
|
|
||||||
user.roles = Promise.resolve(roles)
|
user.roles = Promise.resolve(roles)
|
||||||
|
|
||||||
Object.assign(user, registrationFields)
|
Object.assign(user, registrationFields)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ describe('TraceSession', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
sessionTraceRepository = {} as jest.Mocked<SessionTraceRepositoryInterface>
|
sessionTraceRepository = {} as jest.Mocked<SessionTraceRepositoryInterface>
|
||||||
sessionTraceRepository.findOneByUserUuidAndDate = jest.fn().mockReturnValue(null)
|
sessionTraceRepository.findOneByUserUuidAndDate = jest.fn().mockReturnValue(null)
|
||||||
sessionTraceRepository.save = jest.fn()
|
sessionTraceRepository.insert = jest.fn()
|
||||||
|
|
||||||
timer = {} as jest.Mocked<TimerInterface>
|
timer = {} as jest.Mocked<TimerInterface>
|
||||||
timer.getUTCDateNDaysAhead = jest.fn().mockReturnValue(new Date())
|
timer.getUTCDateNDaysAhead = jest.fn().mockReturnValue(new Date())
|
||||||
@@ -30,7 +30,7 @@ describe('TraceSession', () => {
|
|||||||
|
|
||||||
expect(result.isFailed()).toBe(false)
|
expect(result.isFailed()).toBe(false)
|
||||||
expect(result.getValue().props.userUuid.value).toEqual('0702b137-4f5c-438a-915e-8f8b46572ce5')
|
expect(result.getValue().props.userUuid.value).toEqual('0702b137-4f5c-438a-915e-8f8b46572ce5')
|
||||||
expect(sessionTraceRepository.save).toHaveBeenCalledTimes(1)
|
expect(sessionTraceRepository.insert).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not save a session trace if one already exists for the same user and date', async () => {
|
it('should not save a session trace if one already exists for the same user and date', async () => {
|
||||||
@@ -43,7 +43,7 @@ describe('TraceSession', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
expect(result.isFailed()).toBe(false)
|
expect(result.isFailed()).toBe(false)
|
||||||
expect(sessionTraceRepository.save).not.toHaveBeenCalled()
|
expect(sessionTraceRepository.insert).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return an error if userUuid is invalid', async () => {
|
it('should return an error if userUuid is invalid', async () => {
|
||||||
@@ -54,7 +54,7 @@ describe('TraceSession', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
expect(result.isFailed()).toBe(true)
|
expect(result.isFailed()).toBe(true)
|
||||||
expect(sessionTraceRepository.save).not.toHaveBeenCalled()
|
expect(sessionTraceRepository.insert).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return an error if username is invalid', async () => {
|
it('should return an error if username is invalid', async () => {
|
||||||
@@ -65,7 +65,7 @@ describe('TraceSession', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
expect(result.isFailed()).toBe(true)
|
expect(result.isFailed()).toBe(true)
|
||||||
expect(sessionTraceRepository.save).not.toHaveBeenCalled()
|
expect(sessionTraceRepository.insert).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return an error if subscriptionPlanName is invalid', async () => {
|
it('should return an error if subscriptionPlanName is invalid', async () => {
|
||||||
@@ -76,7 +76,7 @@ describe('TraceSession', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
expect(result.isFailed()).toBe(true)
|
expect(result.isFailed()).toBe(true)
|
||||||
expect(sessionTraceRepository.save).not.toHaveBeenCalled()
|
expect(sessionTraceRepository.insert).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not save a session trace if creating of the session trace fails', async () => {
|
it('should not save a session trace if creating of the session trace fails', async () => {
|
||||||
@@ -90,7 +90,7 @@ describe('TraceSession', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
expect(result.isFailed()).toBe(true)
|
expect(result.isFailed()).toBe(true)
|
||||||
expect(sessionTraceRepository.save).not.toHaveBeenCalled()
|
expect(sessionTraceRepository.insert).not.toHaveBeenCalled()
|
||||||
|
|
||||||
mock.mockRestore()
|
mock.mockRestore()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export class TraceSession implements UseCaseInterface<SessionTrace> {
|
|||||||
}
|
}
|
||||||
const sessionTrace = sessionTraceOrError.getValue()
|
const sessionTrace = sessionTraceOrError.getValue()
|
||||||
|
|
||||||
await this.sessionTraceRepository.save(sessionTrace)
|
await this.sessionTraceRepository.insert(sessionTrace)
|
||||||
|
|
||||||
return Result.ok<SessionTrace>(sessionTrace)
|
return Result.ok<SessionTrace>(sessionTrace)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ import { CrossServiceTokenData, TokenDecoderInterface } from '@standardnotes/sec
|
|||||||
import { NextFunction, Request, Response } from 'express'
|
import { NextFunction, Request, Response } from 'express'
|
||||||
import { BaseMiddleware } from 'inversify-express-utils'
|
import { BaseMiddleware } from 'inversify-express-utils'
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
|
import { Segment, getSegment } from 'aws-xray-sdk'
|
||||||
|
|
||||||
export abstract class ApiGatewayAuthMiddleware extends BaseMiddleware {
|
export abstract class ApiGatewayAuthMiddleware extends BaseMiddleware {
|
||||||
constructor(
|
constructor(
|
||||||
private tokenDecoder: TokenDecoderInterface<CrossServiceTokenData>,
|
private tokenDecoder: TokenDecoderInterface<CrossServiceTokenData>,
|
||||||
|
private isConfiguredForAWSProduction: boolean,
|
||||||
private logger: Logger,
|
private logger: Logger,
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
@@ -39,6 +41,13 @@ export abstract class ApiGatewayAuthMiddleware extends BaseMiddleware {
|
|||||||
response.locals.session = token.session
|
response.locals.session = token.session
|
||||||
response.locals.readOnlyAccess = token.session?.readonly_access ?? false
|
response.locals.readOnlyAccess = token.session?.readonly_access ?? false
|
||||||
|
|
||||||
|
if (this.isConfiguredForAWSProduction) {
|
||||||
|
const segment = getSegment()
|
||||||
|
if (segment instanceof Segment) {
|
||||||
|
segment.setUser(token.user.uuid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return next()
|
return next()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return next(error)
|
return next(error)
|
||||||
|
|||||||
+4
-6
@@ -1,18 +1,16 @@
|
|||||||
import { CrossServiceTokenData, TokenDecoderInterface } from '@standardnotes/security'
|
import { CrossServiceTokenData, TokenDecoderInterface } from '@standardnotes/security'
|
||||||
import { NextFunction, Request, Response } from 'express'
|
import { NextFunction, Request, Response } from 'express'
|
||||||
import { inject, injectable } from 'inversify'
|
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
|
|
||||||
import TYPES from '../../../Bootstrap/Types'
|
|
||||||
import { ApiGatewayAuthMiddleware } from './ApiGatewayAuthMiddleware'
|
import { ApiGatewayAuthMiddleware } from './ApiGatewayAuthMiddleware'
|
||||||
|
|
||||||
@injectable()
|
|
||||||
export class OptionalCrossServiceTokenMiddleware extends ApiGatewayAuthMiddleware {
|
export class OptionalCrossServiceTokenMiddleware extends ApiGatewayAuthMiddleware {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.Auth_CrossServiceTokenDecoder) tokenDecoder: TokenDecoderInterface<CrossServiceTokenData>,
|
tokenDecoder: TokenDecoderInterface<CrossServiceTokenData>,
|
||||||
@inject(TYPES.Auth_Logger) logger: Logger,
|
isConfiguredForAWSProduction: boolean,
|
||||||
|
logger: Logger,
|
||||||
) {
|
) {
|
||||||
super(tokenDecoder, logger)
|
super(tokenDecoder, isConfiguredForAWSProduction, logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override handleMissingToken(request: Request, _response: Response, next: NextFunction): boolean {
|
protected override handleMissingToken(request: Request, _response: Response, next: NextFunction): boolean {
|
||||||
|
|||||||
+4
-6
@@ -1,18 +1,16 @@
|
|||||||
import { CrossServiceTokenData, TokenDecoderInterface } from '@standardnotes/security'
|
import { CrossServiceTokenData, TokenDecoderInterface } from '@standardnotes/security'
|
||||||
import { NextFunction, Request, Response } from 'express'
|
import { NextFunction, Request, Response } from 'express'
|
||||||
import { inject, injectable } from 'inversify'
|
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
|
|
||||||
import TYPES from '../../../Bootstrap/Types'
|
|
||||||
import { ApiGatewayAuthMiddleware } from './ApiGatewayAuthMiddleware'
|
import { ApiGatewayAuthMiddleware } from './ApiGatewayAuthMiddleware'
|
||||||
|
|
||||||
@injectable()
|
|
||||||
export class RequiredCrossServiceTokenMiddleware extends ApiGatewayAuthMiddleware {
|
export class RequiredCrossServiceTokenMiddleware extends ApiGatewayAuthMiddleware {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.Auth_CrossServiceTokenDecoder) tokenDecoder: TokenDecoderInterface<CrossServiceTokenData>,
|
tokenDecoder: TokenDecoderInterface<CrossServiceTokenData>,
|
||||||
@inject(TYPES.Auth_Logger) logger: Logger,
|
isConfiguredForAWSProduction: boolean,
|
||||||
|
logger: Logger,
|
||||||
) {
|
) {
|
||||||
super(tokenDecoder, logger)
|
super(tokenDecoder, isConfiguredForAWSProduction, logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override handleMissingToken(request: Request, response: Response, _next: NextFunction): boolean {
|
protected override handleMissingToken(request: Request, response: Response, _next: NextFunction): boolean {
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ export class RedisTransitionStatusRepository implements TransitionStatusReposito
|
|||||||
await this.redisClient.set(`${this.PREFIX}:${transitionType}:${userUuid}`, status.value)
|
await this.redisClient.set(`${this.PREFIX}:${transitionType}:${userUuid}`, status.value)
|
||||||
break
|
break
|
||||||
case TransitionStatus.STATUSES.InProgress: {
|
case TransitionStatus.STATUSES.InProgress: {
|
||||||
const ttl2Hourse = 7_200
|
const ttl24Hours = 86_400
|
||||||
await this.redisClient.setex(`${this.PREFIX}:${transitionType}:${userUuid}`, ttl2Hourse, status.value)
|
await this.redisClient.setex(`${this.PREFIX}:${transitionType}:${userUuid}`, ttl24Hours, status.value)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { MapperInterface, SubscriptionPlanName, Uuid } from '@standardnotes/domain-core'
|
import { MapperInterface, SubscriptionPlanName, Uuid } from '@standardnotes/domain-core'
|
||||||
|
import { TimerInterface } from '@standardnotes/time'
|
||||||
import { Repository } from 'typeorm'
|
import { Repository } from 'typeorm'
|
||||||
|
|
||||||
import { SessionTrace } from '../../Domain/Session/SessionTrace'
|
import { SessionTrace } from '../../Domain/Session/SessionTrace'
|
||||||
import { SessionTraceRepositoryInterface } from '../../Domain/Session/SessionTraceRepositoryInterface'
|
import { SessionTraceRepositoryInterface } from '../../Domain/Session/SessionTraceRepositoryInterface'
|
||||||
import { TypeORMSessionTrace } from './TypeORMSessionTrace'
|
import { TypeORMSessionTrace } from './TypeORMSessionTrace'
|
||||||
@@ -8,13 +10,14 @@ export class TypeORMSessionTraceRepository implements SessionTraceRepositoryInte
|
|||||||
constructor(
|
constructor(
|
||||||
private ormRepository: Repository<TypeORMSessionTrace>,
|
private ormRepository: Repository<TypeORMSessionTrace>,
|
||||||
private mapper: MapperInterface<SessionTrace, TypeORMSessionTrace>,
|
private mapper: MapperInterface<SessionTrace, TypeORMSessionTrace>,
|
||||||
|
private timer: TimerInterface,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async countByDateAndSubscriptionPlanName(date: Date, subscriptionPlanName: SubscriptionPlanName): Promise<number> {
|
async countByDateAndSubscriptionPlanName(date: Date, subscriptionPlanName: SubscriptionPlanName): Promise<number> {
|
||||||
return this.ormRepository
|
return this.ormRepository
|
||||||
.createQueryBuilder('trace')
|
.createQueryBuilder('trace')
|
||||||
.where('trace.creation_date = :creationDate', {
|
.where('trace.creation_date = :creationDate', {
|
||||||
creationDate: `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`,
|
creationDate: this.timer.convertDateToFormattedString(date, 'YYYY-MM-DD'),
|
||||||
})
|
})
|
||||||
.andWhere('trace.subscription_plan_name = :subscriptionPlanName', {
|
.andWhere('trace.subscription_plan_name = :subscriptionPlanName', {
|
||||||
subscriptionPlanName: subscriptionPlanName.value,
|
subscriptionPlanName: subscriptionPlanName.value,
|
||||||
@@ -26,7 +29,7 @@ export class TypeORMSessionTraceRepository implements SessionTraceRepositoryInte
|
|||||||
return this.ormRepository
|
return this.ormRepository
|
||||||
.createQueryBuilder('trace')
|
.createQueryBuilder('trace')
|
||||||
.where('trace.creation_date = :creationDate', {
|
.where('trace.creation_date = :creationDate', {
|
||||||
creationDate: `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`,
|
creationDate: this.timer.convertDateToFormattedString(date, 'YYYY-MM-DD'),
|
||||||
})
|
})
|
||||||
.getCount()
|
.getCount()
|
||||||
}
|
}
|
||||||
@@ -44,7 +47,7 @@ export class TypeORMSessionTraceRepository implements SessionTraceRepositoryInte
|
|||||||
.createQueryBuilder('trace')
|
.createQueryBuilder('trace')
|
||||||
.where('trace.user_uuid = :userUuid AND trace.creation_date = :creationDate', {
|
.where('trace.user_uuid = :userUuid AND trace.creation_date = :creationDate', {
|
||||||
userUuid: userUuid.value,
|
userUuid: userUuid.value,
|
||||||
creationDate: `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`,
|
creationDate: this.timer.convertDateToFormattedString(date, 'YYYY-MM-DD'),
|
||||||
})
|
})
|
||||||
.getOne()
|
.getOne()
|
||||||
|
|
||||||
@@ -55,9 +58,9 @@ export class TypeORMSessionTraceRepository implements SessionTraceRepositoryInte
|
|||||||
return this.mapper.toDomain(typeOrm)
|
return this.mapper.toDomain(typeOrm)
|
||||||
}
|
}
|
||||||
|
|
||||||
async save(sessionTrace: SessionTrace): Promise<void> {
|
async insert(sessionTrace: SessionTrace): Promise<void> {
|
||||||
const persistence = this.mapper.toProjection(sessionTrace)
|
const persistence = this.mapper.toProjection(sessionTrace)
|
||||||
|
|
||||||
await this.ormRepository.save(persistence)
|
await this.ormRepository.insert(persistence)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import { MapperInterface, SubscriptionPlanName, UniqueEntityId, Username, Uuid } from '@standardnotes/domain-core'
|
import { MapperInterface, SubscriptionPlanName, UniqueEntityId, Username, Uuid } from '@standardnotes/domain-core'
|
||||||
import { SessionTrace } from '../Domain/Session/SessionTrace'
|
import { SessionTrace } from '../Domain/Session/SessionTrace'
|
||||||
import { TypeORMSessionTrace } from '../Infra/TypeORM/TypeORMSessionTrace'
|
import { TypeORMSessionTrace } from '../Infra/TypeORM/TypeORMSessionTrace'
|
||||||
|
import { TimerInterface } from '@standardnotes/time'
|
||||||
|
|
||||||
export class SessionTracePersistenceMapper implements MapperInterface<SessionTrace, TypeORMSessionTrace> {
|
export class SessionTracePersistenceMapper implements MapperInterface<SessionTrace, TypeORMSessionTrace> {
|
||||||
|
constructor(private timer: TimerInterface) {}
|
||||||
|
|
||||||
toDomain(projection: TypeORMSessionTrace): SessionTrace {
|
toDomain(projection: TypeORMSessionTrace): SessionTrace {
|
||||||
const userUuidOrError = Uuid.create(projection.userUuid)
|
const userUuidOrError = Uuid.create(projection.userUuid)
|
||||||
if (userUuidOrError.isFailed()) {
|
if (userUuidOrError.isFailed()) {
|
||||||
@@ -50,11 +53,7 @@ export class SessionTracePersistenceMapper implements MapperInterface<SessionTra
|
|||||||
typeOrm.username = domain.props.username.value
|
typeOrm.username = domain.props.username.value
|
||||||
typeOrm.subscriptionPlanName = domain.props.subscriptionPlanName ? domain.props.subscriptionPlanName.value : null
|
typeOrm.subscriptionPlanName = domain.props.subscriptionPlanName ? domain.props.subscriptionPlanName.value : null
|
||||||
typeOrm.createdAt = domain.props.createdAt
|
typeOrm.createdAt = domain.props.createdAt
|
||||||
typeOrm.creationDate = new Date(
|
typeOrm.creationDate = new Date(this.timer.convertDateToFormattedString(domain.props.createdAt, 'YYYY-MM-DD'))
|
||||||
domain.props.createdAt.getFullYear(),
|
|
||||||
domain.props.createdAt.getMonth(),
|
|
||||||
domain.props.createdAt.getDate(),
|
|
||||||
)
|
|
||||||
typeOrm.expiresAt = domain.props.expiresAt
|
typeOrm.expiresAt = domain.props.expiresAt
|
||||||
|
|
||||||
return typeOrm
|
return typeOrm
|
||||||
|
|||||||
@@ -3,6 +3,18 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.34.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.34.1...@standardnotes/domain-core@1.34.2) (2023-10-04)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* identifying services in workers ([eab78b3](https://github.com/standardnotes/server/commit/eab78b3a95ec82cb779d069d172169bfa92368c9))
|
||||||
|
|
||||||
|
## [1.34.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.34.0...@standardnotes/domain-core@1.34.1) (2023-09-27)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* removing items in a vault and notifying about designated survivor ([#855](https://github.com/standardnotes/server/issues/855)) ([1d06ffe](https://github.com/standardnotes/server/commit/1d06ffe9d51722ada7baa040e1d5ed351fc28f39))
|
||||||
|
|
||||||
# [1.34.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.33.2...@standardnotes/domain-core@1.34.0) (2023-09-26)
|
# [1.34.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.33.2...@standardnotes/domain-core@1.34.0) (2023-09-26)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/domain-core",
|
"name": "@standardnotes/domain-core",
|
||||||
"version": "1.34.0",
|
"version": "1.34.2",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { NotificationPayloadIdentifierTypeProps } from './NotificationPayloadIde
|
|||||||
export class NotificationPayloadIdentifierType extends ValueObject<NotificationPayloadIdentifierTypeProps> {
|
export class NotificationPayloadIdentifierType extends ValueObject<NotificationPayloadIdentifierTypeProps> {
|
||||||
static readonly TYPES = {
|
static readonly TYPES = {
|
||||||
SharedVaultUuid: 'shared_vault_uuid',
|
SharedVaultUuid: 'shared_vault_uuid',
|
||||||
|
UserUuid: 'user_uuid',
|
||||||
SharedVaultInviteUuid: 'shared_vault_invite_uuid',
|
SharedVaultInviteUuid: 'shared_vault_invite_uuid',
|
||||||
ItemUuid: 'item_uuid',
|
ItemUuid: 'item_uuid',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export class NotificationType extends ValueObject<NotificationTypeProps> {
|
|||||||
SharedVaultItemRemoved: 'shared_vault_item_removed',
|
SharedVaultItemRemoved: 'shared_vault_item_removed',
|
||||||
SelfRemovedFromSharedVault: 'self_removed_from_shared_vault',
|
SelfRemovedFromSharedVault: 'self_removed_from_shared_vault',
|
||||||
UserRemovedFromSharedVault: 'user_removed_from_shared_vault',
|
UserRemovedFromSharedVault: 'user_removed_from_shared_vault',
|
||||||
|
UserDesignatedAsSurvivor: 'user_designated_as_survivor',
|
||||||
UserAddedToSharedVault: 'user_added_to_shared_vault',
|
UserAddedToSharedVault: 'user_added_to_shared_vault',
|
||||||
SharedVaultInviteCanceled: 'shared_vault_invite_canceled',
|
SharedVaultInviteCanceled: 'shared_vault_invite_canceled',
|
||||||
SharedVaultFileUploaded: 'shared_vault_file_uploaded',
|
SharedVaultFileUploaded: 'shared_vault_file_uploaded',
|
||||||
|
|||||||
@@ -6,9 +6,13 @@ export class ServiceIdentifier extends ValueObject<ServiceIdentifierProps> {
|
|||||||
static readonly NAMES = {
|
static readonly NAMES = {
|
||||||
ApiGateway: 'ApiGateway',
|
ApiGateway: 'ApiGateway',
|
||||||
Auth: 'Auth',
|
Auth: 'Auth',
|
||||||
|
AuthWorker: 'AuthWorker',
|
||||||
SyncingServer: 'SyncingServer',
|
SyncingServer: 'SyncingServer',
|
||||||
|
SyncingServerWorker: 'SyncingServerWorker',
|
||||||
Revisions: 'Revisions',
|
Revisions: 'Revisions',
|
||||||
|
RevisionsWorker: 'RevisionsWorker',
|
||||||
Files: 'Files',
|
Files: 'Files',
|
||||||
|
FilesWorker: 'FilesWorker',
|
||||||
}
|
}
|
||||||
|
|
||||||
get value(): string {
|
get value(): string {
|
||||||
|
|||||||
@@ -3,6 +3,60 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.14.7](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.14.6...@standardnotes/domain-events-infra@1.14.7) (2023-10-05)
|
||||||
|
|
||||||
|
### Reverts
|
||||||
|
|
||||||
|
* Revert "fix(domain-events-infra): setting user metadata on workers" ([cd37c95](https://github.com/standardnotes/server/commit/cd37c951bbec0f1bf6443792db961efd27380eac))
|
||||||
|
|
||||||
|
## [1.14.6](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.14.5...@standardnotes/domain-events-infra@1.14.6) (2023-10-05)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **domain-events-infra:** setting user metadata on workers ([c4b6f17](https://github.com/standardnotes/server/commit/c4b6f17ebcfe7bd77b6741f881a0d1f13ba809a4))
|
||||||
|
|
||||||
|
## [1.14.5](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.14.4...@standardnotes/domain-events-infra@1.14.5) (2023-10-04)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* identifying services in workers ([eab78b3](https://github.com/standardnotes/server/commit/eab78b3a95ec82cb779d069d172169bfa92368c9))
|
||||||
|
|
||||||
|
## [1.14.4](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.14.3...@standardnotes/domain-events-infra@1.14.4) (2023-10-04)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **domain-events-infra:** subsegment name ([ba7cbb9](https://github.com/standardnotes/server/commit/ba7cbb989ba3592ea0c13fc39f85e314517fbb2d))
|
||||||
|
|
||||||
|
## [1.14.3](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.14.2...@standardnotes/domain-events-infra@1.14.3) (2023-10-04)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **domain-events-infra:** handling segments ([207ef9f](https://github.com/standardnotes/server/commit/207ef9f3e531b730f3f4869fb128354dbd659f46))
|
||||||
|
* **domain-events-infra:** remove redundant flush ([64f1fe5](https://github.com/standardnotes/server/commit/64f1fe59c23894bda9ad40c6bdeaf2997a8b48ce))
|
||||||
|
|
||||||
|
## [1.14.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.14.1...@standardnotes/domain-events-infra@1.14.2) (2023-10-04)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **domain-events-infra:** handling async functions ([f6bc1c3](https://github.com/standardnotes/server/commit/f6bc1c30846ecfb159f7fb1cdd8bfc3ab15b2dde))
|
||||||
|
* **domain-events-infra:** imports ([7668713](https://github.com/standardnotes/server/commit/7668713dd6f65b65e546152828f5f52ea34f8bf5))
|
||||||
|
|
||||||
|
## [1.14.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.14.0...@standardnotes/domain-events-infra@1.14.1) (2023-10-03)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **domain-events-infra:** change segment closing ([e066b6a](https://github.com/standardnotes/server/commit/e066b6a126754e5b1ea73b8ef5ce9068dc424d77))
|
||||||
|
|
||||||
|
# [1.14.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.13.1...@standardnotes/domain-events-infra@1.14.0) (2023-10-03)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add xray segment tracing on auth-worker ([b1b244a](https://github.com/standardnotes/server/commit/b1b244a2cf1e17ddf67fc9b238b4b25a1bc5a190))
|
||||||
|
|
||||||
|
## [1.13.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.13.0...@standardnotes/domain-events-infra@1.13.1) (2023-09-28)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||||
|
|
||||||
# [1.13.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.12.34...@standardnotes/domain-events-infra@1.13.0) (2023-09-26)
|
# [1.13.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.12.34...@standardnotes/domain-events-infra@1.13.0) (2023-09-26)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/domain-events-infra",
|
"name": "@standardnotes/domain-events-infra",
|
||||||
"version": "1.13.0",
|
"version": "1.14.7",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
"@aws-sdk/client-sns": "^3.332.0",
|
"@aws-sdk/client-sns": "^3.332.0",
|
||||||
"@aws-sdk/client-sqs": "^3.332.0",
|
"@aws-sdk/client-sqs": "^3.332.0",
|
||||||
"@standardnotes/domain-events": "workspace:*",
|
"@standardnotes/domain-events": "workspace:*",
|
||||||
|
"aws-xray-sdk": "^3.5.2",
|
||||||
"ioredis": "^5.2.4",
|
"ioredis": "^5.2.4",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"sqs-consumer": "^6.2.1",
|
"sqs-consumer": "^6.2.1",
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import { Logger } from 'winston'
|
||||||
|
import * as zlib from 'zlib'
|
||||||
|
import { Segment, Subsegment, captureAsyncFunc } from 'aws-xray-sdk'
|
||||||
|
|
||||||
|
import {
|
||||||
|
DomainEventHandlerInterface,
|
||||||
|
DomainEventInterface,
|
||||||
|
DomainEventMessageHandlerInterface,
|
||||||
|
} from '@standardnotes/domain-events'
|
||||||
|
|
||||||
|
export class SQSXRayEventMessageHandler implements DomainEventMessageHandlerInterface {
|
||||||
|
constructor(
|
||||||
|
private serviceName: string,
|
||||||
|
private handlers: Map<string, DomainEventHandlerInterface>,
|
||||||
|
private logger: Logger,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async handleMessage(message: string): Promise<void> {
|
||||||
|
const messageParsed = JSON.parse(message)
|
||||||
|
|
||||||
|
const domainEventJson = zlib.unzipSync(Buffer.from(messageParsed.Message, 'base64')).toString()
|
||||||
|
|
||||||
|
const domainEvent: DomainEventInterface = JSON.parse(domainEventJson)
|
||||||
|
|
||||||
|
domainEvent.createdAt = new Date(domainEvent.createdAt)
|
||||||
|
|
||||||
|
const handler = this.handlers.get(domainEvent.type)
|
||||||
|
if (!handler) {
|
||||||
|
this.logger.debug(`Event handler for event type ${domainEvent.type} does not exist`)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.debug(`Received event: ${domainEvent.type}`)
|
||||||
|
|
||||||
|
const xRaySegment = new Segment(this.serviceName)
|
||||||
|
|
||||||
|
if (domainEvent.meta.correlation.userIdentifierType === 'uuid') {
|
||||||
|
xRaySegment.setUser(domainEvent.meta.correlation.userIdentifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
await captureAsyncFunc(
|
||||||
|
domainEvent.type,
|
||||||
|
async (subsegment?: Subsegment) => {
|
||||||
|
await handler.handle(domainEvent)
|
||||||
|
|
||||||
|
if (subsegment) {
|
||||||
|
subsegment.close()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
xRaySegment,
|
||||||
|
)
|
||||||
|
|
||||||
|
xRaySegment.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleError(error: Error): Promise<void> {
|
||||||
|
this.logger.error('Error occured while handling SQS message: %O', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,3 +12,4 @@ export * from './SQS/SQSNewRelicBounceNotificiationHandler'
|
|||||||
export * from './SQS/SQSDomainEventSubscriberFactory'
|
export * from './SQS/SQSDomainEventSubscriberFactory'
|
||||||
export * from './SQS/SQSEventMessageHandler'
|
export * from './SQS/SQSEventMessageHandler'
|
||||||
export * from './SQS/SQSNewRelicEventMessageHandler'
|
export * from './SQS/SQSNewRelicEventMessageHandler'
|
||||||
|
export * from './SQS/SQSXRayEventMessageHandler'
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [2.131.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.131.0...@standardnotes/domain-events@2.131.1) (2023-09-28)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/domain-events
|
||||||
|
|
||||||
# [2.131.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.130.0...@standardnotes/domain-events@2.131.0) (2023-09-26)
|
# [2.131.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.130.0...@standardnotes/domain-events@2.131.0) (2023-09-26)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/domain-events",
|
"name": "@standardnotes/domain-events",
|
||||||
"version": "2.131.0",
|
"version": "2.131.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,46 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.12.10](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.12.9...@standardnotes/event-store@1.12.10) (2023-10-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.12.9](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.12.8...@standardnotes/event-store@1.12.9) (2023-10-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.12.8](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.12.7...@standardnotes/event-store@1.12.8) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.12.7](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.12.6...@standardnotes/event-store@1.12.7) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.12.6](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.12.5...@standardnotes/event-store@1.12.6) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.12.5](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.12.4...@standardnotes/event-store@1.12.5) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.12.4](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.12.3...@standardnotes/event-store@1.12.4) (2023-10-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.12.3](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.12.2...@standardnotes/event-store@1.12.3) (2023-10-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.12.2](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.12.1...@standardnotes/event-store@1.12.2) (2023-09-28)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.12.1](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.12.0...@standardnotes/event-store@1.12.1) (2023-09-27)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
# [1.12.0](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.52...@standardnotes/event-store@1.12.0) (2023-09-26)
|
# [1.12.0](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.52...@standardnotes/event-store@1.12.0) (2023-09-26)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/event-store",
|
"name": "@standardnotes/event-store",
|
||||||
"version": "1.12.0",
|
"version": "1.12.10",
|
||||||
"description": "Event Store Service",
|
"description": "Event Store Service",
|
||||||
"private": true,
|
"private": true,
|
||||||
"main": "dist/src/index.js",
|
"main": "dist/src/index.js",
|
||||||
|
|||||||
@@ -3,6 +3,54 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.26.2](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.26.1...@standardnotes/files-server@1.26.2) (2023-10-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
## [1.26.1](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.26.0...@standardnotes/files-server@1.26.1) (2023-10-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
# [1.26.0](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.25.6...@standardnotes/files-server@1.26.0) (2023-10-04)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add xray to syncing server and files ([6583ff6](https://github.com/standardnotes/files/commit/6583ff6cd90f7881c1a79c0f904f1b1db96fc5b3))
|
||||||
|
|
||||||
|
## [1.25.6](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.25.5...@standardnotes/files-server@1.25.6) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
## [1.25.5](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.25.4...@standardnotes/files-server@1.25.5) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
## [1.25.4](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.25.3...@standardnotes/files-server@1.25.4) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
## [1.25.3](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.25.2...@standardnotes/files-server@1.25.3) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
## [1.25.2](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.25.1...@standardnotes/files-server@1.25.2) (2023-10-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
## [1.25.1](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.25.0...@standardnotes/files-server@1.25.1) (2023-10-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
# [1.25.0](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.24.1...@standardnotes/files-server@1.25.0) (2023-09-28)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* block file operations during transition ([#856](https://github.com/standardnotes/files/issues/856)) ([676cf36](https://github.com/standardnotes/files/commit/676cf36f8d769aa433880b2800f0457d06fbbf14))
|
||||||
|
|
||||||
|
## [1.24.1](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.24.0...@standardnotes/files-server@1.24.1) (2023-09-27)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
# [1.24.0](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.23.2...@standardnotes/files-server@1.24.0) (2023-09-26)
|
# [1.24.0](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.23.2...@standardnotes/files-server@1.24.0) (2023-09-26)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import helmet from 'helmet'
|
|||||||
import * as cors from 'cors'
|
import * as cors from 'cors'
|
||||||
import { urlencoded, json, raw, Request, Response, NextFunction } from 'express'
|
import { urlencoded, json, raw, Request, Response, NextFunction } from 'express'
|
||||||
import * as winston from 'winston'
|
import * as winston from 'winston'
|
||||||
|
import * as AWSXRay from 'aws-xray-sdk'
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const robots = require('express-robots-txt')
|
const robots = require('express-robots-txt')
|
||||||
|
|
||||||
@@ -17,15 +18,27 @@ import { InversifyExpressServer } from 'inversify-express-utils'
|
|||||||
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
||||||
import TYPES from '../src/Bootstrap/Types'
|
import TYPES from '../src/Bootstrap/Types'
|
||||||
import { Env } from '../src/Bootstrap/Env'
|
import { Env } from '../src/Bootstrap/Env'
|
||||||
|
import { ServiceIdentifier } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
const container = new ContainerConfigLoader()
|
const container = new ContainerConfigLoader()
|
||||||
void container.load().then((container) => {
|
void container.load().then((container) => {
|
||||||
const env: Env = new Env()
|
const env: Env = new Env()
|
||||||
env.load()
|
env.load()
|
||||||
|
|
||||||
|
const isConfiguredForAWSProduction =
|
||||||
|
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
|
||||||
|
|
||||||
|
if (isConfiguredForAWSProduction) {
|
||||||
|
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
|
||||||
|
}
|
||||||
|
|
||||||
const server = new InversifyExpressServer(container)
|
const server = new InversifyExpressServer(container)
|
||||||
|
|
||||||
server.setConfig((app) => {
|
server.setConfig((app) => {
|
||||||
|
if (isConfiguredForAWSProduction) {
|
||||||
|
app.use(AWSXRay.express.openSegment(ServiceIdentifier.NAMES.Files))
|
||||||
|
}
|
||||||
|
|
||||||
app.use((_request: Request, response: Response, next: NextFunction) => {
|
app.use((_request: Request, response: Response, next: NextFunction) => {
|
||||||
response.setHeader('X-Files-Version', container.get(TYPES.Files_VERSION))
|
response.setHeader('X-Files-Version', container.get(TYPES.Files_VERSION))
|
||||||
next()
|
next()
|
||||||
@@ -90,6 +103,10 @@ void container.load().then((container) => {
|
|||||||
|
|
||||||
const serverInstance = server.build()
|
const serverInstance = server.build()
|
||||||
|
|
||||||
|
if (isConfiguredForAWSProduction) {
|
||||||
|
serverInstance.use(AWSXRay.express.closeSegment())
|
||||||
|
}
|
||||||
|
|
||||||
serverInstance.listen(env.get('PORT'))
|
serverInstance.listen(env.get('PORT'))
|
||||||
|
|
||||||
logger.info(`Server started on port ${process.env.PORT}`)
|
logger.info(`Server started on port ${process.env.PORT}`)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { Env } from '../src/Bootstrap/Env'
|
|||||||
import { DomainEventSubscriberFactoryInterface } from '@standardnotes/domain-events'
|
import { DomainEventSubscriberFactoryInterface } from '@standardnotes/domain-events'
|
||||||
import * as dayjs from 'dayjs'
|
import * as dayjs from 'dayjs'
|
||||||
import * as utc from 'dayjs/plugin/utc'
|
import * as utc from 'dayjs/plugin/utc'
|
||||||
|
import * as AWSXRay from 'aws-xray-sdk'
|
||||||
|
|
||||||
const container = new ContainerConfigLoader()
|
const container = new ContainerConfigLoader()
|
||||||
void container.load().then((container) => {
|
void container.load().then((container) => {
|
||||||
@@ -16,6 +17,14 @@ void container.load().then((container) => {
|
|||||||
const env: Env = new Env()
|
const env: Env = new Env()
|
||||||
env.load()
|
env.load()
|
||||||
|
|
||||||
|
const isConfiguredForAWSProduction =
|
||||||
|
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
|
||||||
|
|
||||||
|
if (isConfiguredForAWSProduction) {
|
||||||
|
AWSXRay.enableManualMode()
|
||||||
|
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
|
||||||
|
}
|
||||||
|
|
||||||
const logger: Logger = container.get(TYPES.Files_Logger)
|
const logger: Logger = container.get(TYPES.Files_Logger)
|
||||||
|
|
||||||
logger.info('Starting worker...')
|
logger.info('Starting worker...')
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/files-server",
|
"name": "@standardnotes/files-server",
|
||||||
"version": "1.24.0",
|
"version": "1.26.2",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
@@ -37,6 +37,7 @@
|
|||||||
"@standardnotes/sncrypto-common": "^1.13.4",
|
"@standardnotes/sncrypto-common": "^1.13.4",
|
||||||
"@standardnotes/sncrypto-node": "workspace:*",
|
"@standardnotes/sncrypto-node": "workspace:*",
|
||||||
"@standardnotes/time": "workspace:*",
|
"@standardnotes/time": "workspace:*",
|
||||||
|
"aws-xray-sdk": "^3.5.2",
|
||||||
"connect-busboy": "^1.0.0",
|
"connect-busboy": "^1.0.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dayjs": "^1.11.6",
|
"dayjs": "^1.11.6",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import * as winston from 'winston'
|
import * as winston from 'winston'
|
||||||
import Redis from 'ioredis'
|
import Redis from 'ioredis'
|
||||||
|
import { captureAWSv3Client } from 'aws-xray-sdk'
|
||||||
import { SNSClient, SNSClientConfig } from '@aws-sdk/client-sns'
|
import { SNSClient, SNSClientConfig } from '@aws-sdk/client-sns'
|
||||||
import { SQSClient, SQSClientConfig } from '@aws-sdk/client-sqs'
|
import { SQSClient, SQSClientConfig } from '@aws-sdk/client-sqs'
|
||||||
import { S3Client, S3ClientConfig } from '@aws-sdk/client-s3'
|
import { S3Client, S3ClientConfig } from '@aws-sdk/client-s3'
|
||||||
@@ -19,7 +20,7 @@ import {
|
|||||||
SNSDomainEventPublisher,
|
SNSDomainEventPublisher,
|
||||||
SQSDomainEventSubscriberFactory,
|
SQSDomainEventSubscriberFactory,
|
||||||
SQSEventMessageHandler,
|
SQSEventMessageHandler,
|
||||||
SQSNewRelicEventMessageHandler,
|
SQSXRayEventMessageHandler,
|
||||||
} from '@standardnotes/domain-events-infra'
|
} from '@standardnotes/domain-events-infra'
|
||||||
import { StreamDownloadFile } from '../Domain/UseCase/StreamDownloadFile/StreamDownloadFile'
|
import { StreamDownloadFile } from '../Domain/UseCase/StreamDownloadFile/StreamDownloadFile'
|
||||||
import { FileDownloaderInterface } from '../Domain/Services/FileDownloaderInterface'
|
import { FileDownloaderInterface } from '../Domain/Services/FileDownloaderInterface'
|
||||||
@@ -53,6 +54,7 @@ import { S3FileMover } from '../Infra/S3/S3FileMover'
|
|||||||
import { FSFileMover } from '../Infra/FS/FSFileMover'
|
import { FSFileMover } from '../Infra/FS/FSFileMover'
|
||||||
import { MoveFile } from '../Domain/UseCase/MoveFile/MoveFile'
|
import { MoveFile } from '../Domain/UseCase/MoveFile/MoveFile'
|
||||||
import { SharedVaultValetTokenAuthMiddleware } from '../Infra/InversifyExpress/Middleware/SharedVaultValetTokenAuthMiddleware'
|
import { SharedVaultValetTokenAuthMiddleware } from '../Infra/InversifyExpress/Middleware/SharedVaultValetTokenAuthMiddleware'
|
||||||
|
import { ServiceIdentifier } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
export class ContainerConfigLoader {
|
export class ContainerConfigLoader {
|
||||||
async load(configuration?: {
|
async load(configuration?: {
|
||||||
@@ -83,7 +85,9 @@ export class ContainerConfigLoader {
|
|||||||
.toConstantValue(env.get('FILE_UPLOAD_PATH', true) ?? `${__dirname}/../../uploads`)
|
.toConstantValue(env.get('FILE_UPLOAD_PATH', true) ?? `${__dirname}/../../uploads`)
|
||||||
|
|
||||||
const isConfiguredForHomeServer = env.get('MODE', true) === 'home-server'
|
const isConfiguredForHomeServer = env.get('MODE', true) === 'home-server'
|
||||||
|
const isConfiguredForSelfHosting = env.get('MODE', true) === 'self-hosted'
|
||||||
const isConfiguredForInMemoryCache = env.get('CACHE_TYPE', true) === 'memory'
|
const isConfiguredForInMemoryCache = env.get('CACHE_TYPE', true) === 'memory'
|
||||||
|
const isConfiguredForAWSProduction = !isConfiguredForHomeServer && !isConfiguredForSelfHosting
|
||||||
|
|
||||||
let logger: winston.Logger
|
let logger: winston.Logger
|
||||||
if (configuration?.logger) {
|
if (configuration?.logger) {
|
||||||
@@ -149,7 +153,11 @@ export class ContainerConfigLoader {
|
|||||||
secretAccessKey: env.get('SNS_SECRET_ACCESS_KEY', true),
|
secretAccessKey: env.get('SNS_SECRET_ACCESS_KEY', true),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
container.bind<SNSClient>(TYPES.Files_SNS).toConstantValue(new SNSClient(snsConfig))
|
let snsClient = new SNSClient(snsConfig)
|
||||||
|
if (isConfiguredForAWSProduction) {
|
||||||
|
snsClient = captureAWSv3Client(snsClient)
|
||||||
|
}
|
||||||
|
container.bind<SNSClient>(TYPES.Files_SNS).toConstantValue(snsClient)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (env.get('SQS_QUEUE_URL', true)) {
|
if (env.get('SQS_QUEUE_URL', true)) {
|
||||||
@@ -165,7 +173,11 @@ export class ContainerConfigLoader {
|
|||||||
secretAccessKey: env.get('SQS_SECRET_ACCESS_KEY', true),
|
secretAccessKey: env.get('SQS_SECRET_ACCESS_KEY', true),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
container.bind<SQSClient>(TYPES.Files_SQS).toConstantValue(new SQSClient(sqsConfig))
|
let sqsClient = new SQSClient(sqsConfig)
|
||||||
|
if (isConfiguredForAWSProduction) {
|
||||||
|
sqsClient = captureAWSv3Client(sqsClient)
|
||||||
|
}
|
||||||
|
container.bind<SQSClient>(TYPES.Files_SQS).toConstantValue(sqsClient)
|
||||||
}
|
}
|
||||||
|
|
||||||
container
|
container
|
||||||
@@ -185,7 +197,10 @@ export class ContainerConfigLoader {
|
|||||||
if (env.get('S3_ENDPOINT', true)) {
|
if (env.get('S3_ENDPOINT', true)) {
|
||||||
s3Opts.endpoint = env.get('S3_ENDPOINT', true)
|
s3Opts.endpoint = env.get('S3_ENDPOINT', true)
|
||||||
}
|
}
|
||||||
const s3Client = new S3Client(s3Opts)
|
let s3Client = new S3Client(s3Opts)
|
||||||
|
if (isConfiguredForAWSProduction) {
|
||||||
|
s3Client = captureAWSv3Client(s3Client)
|
||||||
|
}
|
||||||
container.bind<S3Client>(TYPES.Files_S3).toConstantValue(s3Client)
|
container.bind<S3Client>(TYPES.Files_S3).toConstantValue(s3Client)
|
||||||
container.bind<FileDownloaderInterface>(TYPES.Files_FileDownloader).to(S3FileDownloader)
|
container.bind<FileDownloaderInterface>(TYPES.Files_FileDownloader).to(S3FileDownloader)
|
||||||
container.bind<FileUploaderInterface>(TYPES.Files_FileUploader).to(S3FileUploader)
|
container.bind<FileUploaderInterface>(TYPES.Files_FileUploader).to(S3FileUploader)
|
||||||
@@ -198,7 +213,9 @@ export class ContainerConfigLoader {
|
|||||||
.toConstantValue(
|
.toConstantValue(
|
||||||
new FSFileUploader(container.get(TYPES.Files_FILE_UPLOAD_PATH), container.get(TYPES.Files_Logger)),
|
new FSFileUploader(container.get(TYPES.Files_FILE_UPLOAD_PATH), container.get(TYPES.Files_Logger)),
|
||||||
)
|
)
|
||||||
container.bind<FileRemoverInterface>(TYPES.Files_FileRemover).to(FSFileRemover)
|
container
|
||||||
|
.bind<FileRemoverInterface>(TYPES.Files_FileRemover)
|
||||||
|
.toConstantValue(new FSFileRemover(container.get<string>(TYPES.Files_FILE_UPLOAD_PATH)))
|
||||||
container.bind<FileMoverInterface>(TYPES.Files_FileMover).to(FSFileMover)
|
container.bind<FileMoverInterface>(TYPES.Files_FileMover).to(FSFileMover)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,12 +264,26 @@ export class ContainerConfigLoader {
|
|||||||
// Handlers
|
// Handlers
|
||||||
container
|
container
|
||||||
.bind<AccountDeletionRequestedEventHandler>(TYPES.Files_AccountDeletionRequestedEventHandler)
|
.bind<AccountDeletionRequestedEventHandler>(TYPES.Files_AccountDeletionRequestedEventHandler)
|
||||||
.to(AccountDeletionRequestedEventHandler)
|
.toConstantValue(
|
||||||
|
new AccountDeletionRequestedEventHandler(
|
||||||
|
container.get<MarkFilesToBeRemoved>(TYPES.Files_MarkFilesToBeRemoved),
|
||||||
|
container.get<DomainEventPublisherInterface>(TYPES.Files_DomainEventPublisher),
|
||||||
|
container.get<DomainEventFactoryInterface>(TYPES.Files_DomainEventFactory),
|
||||||
|
container.get<winston.Logger>(TYPES.Files_Logger),
|
||||||
|
),
|
||||||
|
)
|
||||||
container
|
container
|
||||||
.bind<SharedSubscriptionInvitationCanceledEventHandler>(
|
.bind<SharedSubscriptionInvitationCanceledEventHandler>(
|
||||||
TYPES.Files_SharedSubscriptionInvitationCanceledEventHandler,
|
TYPES.Files_SharedSubscriptionInvitationCanceledEventHandler,
|
||||||
)
|
)
|
||||||
.to(SharedSubscriptionInvitationCanceledEventHandler)
|
.toConstantValue(
|
||||||
|
new SharedSubscriptionInvitationCanceledEventHandler(
|
||||||
|
container.get<MarkFilesToBeRemoved>(TYPES.Files_MarkFilesToBeRemoved),
|
||||||
|
container.get<DomainEventPublisherInterface>(TYPES.Files_DomainEventPublisher),
|
||||||
|
container.get<DomainEventFactoryInterface>(TYPES.Files_DomainEventFactory),
|
||||||
|
container.get<winston.Logger>(TYPES.Files_Logger),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
|
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
|
||||||
['ACCOUNT_DELETION_REQUESTED', container.get(TYPES.Files_AccountDeletionRequestedEventHandler)],
|
['ACCOUNT_DELETION_REQUESTED', container.get(TYPES.Files_AccountDeletionRequestedEventHandler)],
|
||||||
@@ -276,7 +307,11 @@ export class ContainerConfigLoader {
|
|||||||
.bind<DomainEventMessageHandlerInterface>(TYPES.Files_DomainEventMessageHandler)
|
.bind<DomainEventMessageHandlerInterface>(TYPES.Files_DomainEventMessageHandler)
|
||||||
.toConstantValue(
|
.toConstantValue(
|
||||||
env.get('NEW_RELIC_ENABLED', true) === 'true'
|
env.get('NEW_RELIC_ENABLED', true) === 'true'
|
||||||
? new SQSNewRelicEventMessageHandler(eventHandlers, container.get(TYPES.Files_Logger))
|
? new SQSXRayEventMessageHandler(
|
||||||
|
ServiceIdentifier.NAMES.FilesWorker,
|
||||||
|
eventHandlers,
|
||||||
|
container.get(TYPES.Files_Logger),
|
||||||
|
)
|
||||||
: new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Files_Logger)),
|
: new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Files_Logger)),
|
||||||
)
|
)
|
||||||
container
|
container
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export type RemovedFileDescription = {
|
export type RemovedFileDescription = {
|
||||||
userUuid: string
|
userOrSharedVaultUuid: string
|
||||||
filePath: string
|
filePath: string
|
||||||
fileName: string
|
fileName: string
|
||||||
fileByteSize: number
|
fileByteSize: number
|
||||||
|
|||||||
@@ -3,18 +3,17 @@ import {
|
|||||||
DomainEventHandlerInterface,
|
DomainEventHandlerInterface,
|
||||||
DomainEventPublisherInterface,
|
DomainEventPublisherInterface,
|
||||||
} from '@standardnotes/domain-events'
|
} from '@standardnotes/domain-events'
|
||||||
import { inject, injectable } from 'inversify'
|
import { Logger } from 'winston'
|
||||||
|
|
||||||
import TYPES from '../../Bootstrap/Types'
|
|
||||||
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
||||||
import { MarkFilesToBeRemoved } from '../UseCase/MarkFilesToBeRemoved/MarkFilesToBeRemoved'
|
import { MarkFilesToBeRemoved } from '../UseCase/MarkFilesToBeRemoved/MarkFilesToBeRemoved'
|
||||||
|
|
||||||
@injectable()
|
|
||||||
export class AccountDeletionRequestedEventHandler implements DomainEventHandlerInterface {
|
export class AccountDeletionRequestedEventHandler implements DomainEventHandlerInterface {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.Files_MarkFilesToBeRemoved) private markFilesToBeRemoved: MarkFilesToBeRemoved,
|
private markFilesToBeRemoved: MarkFilesToBeRemoved,
|
||||||
@inject(TYPES.Files_DomainEventPublisher) private domainEventPublisher: DomainEventPublisherInterface,
|
private domainEventPublisher: DomainEventPublisherInterface,
|
||||||
@inject(TYPES.Files_DomainEventFactory) private domainEventFactory: DomainEventFactoryInterface,
|
private domainEventFactory: DomainEventFactoryInterface,
|
||||||
|
private logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async handle(event: AccountDeletionRequestedEvent): Promise<void> {
|
async handle(event: AccountDeletionRequestedEvent): Promise<void> {
|
||||||
@@ -27,16 +26,23 @@ export class AccountDeletionRequestedEventHandler implements DomainEventHandlerI
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (result.isFailed()) {
|
if (result.isFailed()) {
|
||||||
|
this.logger.error(`Could not mark files for removal for user ${event.payload.userUuid}: ${result.getError()}`)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const filesRemoved = result.getValue()
|
const filesRemoved = result.getValue()
|
||||||
|
|
||||||
|
this.logger.debug(`Marked ${filesRemoved.length} files for removal for user ${event.payload.userUuid}`)
|
||||||
|
|
||||||
for (const fileRemoved of filesRemoved) {
|
for (const fileRemoved of filesRemoved) {
|
||||||
await this.domainEventPublisher.publish(
|
await this.domainEventPublisher.publish(
|
||||||
this.domainEventFactory.createFileRemovedEvent({
|
this.domainEventFactory.createFileRemovedEvent({
|
||||||
regularSubscriptionUuid: event.payload.regularSubscriptionUuid,
|
regularSubscriptionUuid: event.payload.regularSubscriptionUuid,
|
||||||
...fileRemoved,
|
userUuid: fileRemoved.userOrSharedVaultUuid,
|
||||||
|
filePath: fileRemoved.filePath,
|
||||||
|
fileName: fileRemoved.fileName,
|
||||||
|
fileByteSize: fileRemoved.fileByteSize,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-7
@@ -3,18 +3,17 @@ import {
|
|||||||
DomainEventHandlerInterface,
|
DomainEventHandlerInterface,
|
||||||
DomainEventPublisherInterface,
|
DomainEventPublisherInterface,
|
||||||
} from '@standardnotes/domain-events'
|
} from '@standardnotes/domain-events'
|
||||||
import { inject, injectable } from 'inversify'
|
import { Logger } from 'winston'
|
||||||
|
|
||||||
import TYPES from '../../Bootstrap/Types'
|
|
||||||
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
||||||
import { MarkFilesToBeRemoved } from '../UseCase/MarkFilesToBeRemoved/MarkFilesToBeRemoved'
|
import { MarkFilesToBeRemoved } from '../UseCase/MarkFilesToBeRemoved/MarkFilesToBeRemoved'
|
||||||
|
|
||||||
@injectable()
|
|
||||||
export class SharedSubscriptionInvitationCanceledEventHandler implements DomainEventHandlerInterface {
|
export class SharedSubscriptionInvitationCanceledEventHandler implements DomainEventHandlerInterface {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.Files_MarkFilesToBeRemoved) private markFilesToBeRemoved: MarkFilesToBeRemoved,
|
private markFilesToBeRemoved: MarkFilesToBeRemoved,
|
||||||
@inject(TYPES.Files_DomainEventPublisher) private domainEventPublisher: DomainEventPublisherInterface,
|
private domainEventPublisher: DomainEventPublisherInterface,
|
||||||
@inject(TYPES.Files_DomainEventFactory) private domainEventFactory: DomainEventFactoryInterface,
|
private domainEventFactory: DomainEventFactoryInterface,
|
||||||
|
private logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async handle(event: SharedSubscriptionInvitationCanceledEvent): Promise<void> {
|
async handle(event: SharedSubscriptionInvitationCanceledEvent): Promise<void> {
|
||||||
@@ -27,16 +26,25 @@ export class SharedSubscriptionInvitationCanceledEventHandler implements DomainE
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (result.isFailed()) {
|
if (result.isFailed()) {
|
||||||
|
this.logger.error(
|
||||||
|
`Could not mark files to be removed for invitee: ${event.payload.inviteeIdentifier}: ${result.getError()}`,
|
||||||
|
)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const filesRemoved = result.getValue()
|
const filesRemoved = result.getValue()
|
||||||
|
|
||||||
|
this.logger.debug(`Marked ${filesRemoved.length} files for removal for invitee ${event.payload.inviteeIdentifier}`)
|
||||||
|
|
||||||
for (const fileRemoved of filesRemoved) {
|
for (const fileRemoved of filesRemoved) {
|
||||||
await this.domainEventPublisher.publish(
|
await this.domainEventPublisher.publish(
|
||||||
this.domainEventFactory.createFileRemovedEvent({
|
this.domainEventFactory.createFileRemovedEvent({
|
||||||
regularSubscriptionUuid: event.payload.inviterSubscriptionUuid,
|
regularSubscriptionUuid: event.payload.inviterSubscriptionUuid,
|
||||||
...fileRemoved,
|
userUuid: fileRemoved.userOrSharedVaultUuid,
|
||||||
|
filePath: fileRemoved.filePath,
|
||||||
|
fileName: fileRemoved.fileName,
|
||||||
|
fileByteSize: fileRemoved.fileByteSize,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ export class SharedVaultRemovedEventHandler implements DomainEventHandlerInterfa
|
|||||||
|
|
||||||
const filesRemoved = result.getValue()
|
const filesRemoved = result.getValue()
|
||||||
|
|
||||||
|
this.logger.debug(
|
||||||
|
`Marked ${filesRemoved.length} files for removal for shared vault ${event.payload.sharedVaultUuid}`,
|
||||||
|
)
|
||||||
|
|
||||||
for (const fileRemoved of filesRemoved) {
|
for (const fileRemoved of filesRemoved) {
|
||||||
await this.domainEventPublisher.publish(
|
await this.domainEventPublisher.publish(
|
||||||
this.domainEventFactory.createSharedVaultFileRemovedEvent({
|
this.domainEventFactory.createSharedVaultFileRemovedEvent({
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ import { RemovedFileDescription } from '../File/RemovedFileDescription'
|
|||||||
|
|
||||||
export interface FileRemoverInterface {
|
export interface FileRemoverInterface {
|
||||||
remove(filePath: string): Promise<number>
|
remove(filePath: string): Promise<number>
|
||||||
markFilesToBeRemoved(userUuid: string): Promise<Array<RemovedFileDescription>>
|
markFilesToBeRemoved(userOrSharedVaultUuid: string): Promise<Array<RemovedFileDescription>>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,42 @@
|
|||||||
import { inject, injectable } from 'inversify'
|
|
||||||
import { promises } from 'fs'
|
import { promises } from 'fs'
|
||||||
|
|
||||||
import { FileRemoverInterface } from '../../Domain/Services/FileRemoverInterface'
|
import { FileRemoverInterface } from '../../Domain/Services/FileRemoverInterface'
|
||||||
import { RemovedFileDescription } from '../../Domain/File/RemovedFileDescription'
|
import { RemovedFileDescription } from '../../Domain/File/RemovedFileDescription'
|
||||||
import TYPES from '../../Bootstrap/Types'
|
|
||||||
|
|
||||||
@injectable()
|
|
||||||
export class FSFileRemover implements FileRemoverInterface {
|
export class FSFileRemover implements FileRemoverInterface {
|
||||||
constructor(@inject(TYPES.Files_FILE_UPLOAD_PATH) private fileUploadPath: string) {}
|
constructor(private fileUploadPath: string) {}
|
||||||
|
|
||||||
async markFilesToBeRemoved(userUuid: string): Promise<Array<RemovedFileDescription>> {
|
async markFilesToBeRemoved(userOrSharedVaultUuid: string): Promise<Array<RemovedFileDescription>> {
|
||||||
await promises.rmdir(`${this.fileUploadPath}/${userUuid}`)
|
const removedFileDescriptions: RemovedFileDescription[] = []
|
||||||
|
|
||||||
return []
|
let directoryExists: boolean
|
||||||
|
try {
|
||||||
|
await promises.access(`${this.fileUploadPath}/${userOrSharedVaultUuid}`)
|
||||||
|
directoryExists = true
|
||||||
|
} catch (error) {
|
||||||
|
directoryExists = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!directoryExists) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const files = await promises.readdir(`${this.fileUploadPath}/${userOrSharedVaultUuid}`, { withFileTypes: true })
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
const filePath = `${this.fileUploadPath}/${userOrSharedVaultUuid}/${file.name}`
|
||||||
|
|
||||||
|
const fileByteSize = await this.remove(`${userOrSharedVaultUuid}/${file.name}`)
|
||||||
|
|
||||||
|
removedFileDescriptions.push({
|
||||||
|
filePath,
|
||||||
|
fileByteSize,
|
||||||
|
userOrSharedVaultUuid,
|
||||||
|
fileName: file.name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return removedFileDescriptions
|
||||||
}
|
}
|
||||||
|
|
||||||
async remove(filePath: string): Promise<number> {
|
async remove(filePath: string): Promise<number> {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ describe('ValetTokenAuthMiddleware', () => {
|
|||||||
|
|
||||||
const logger = {
|
const logger = {
|
||||||
debug: jest.fn(),
|
debug: jest.fn(),
|
||||||
|
error: jest.fn(),
|
||||||
} as unknown as jest.Mocked<Logger>
|
} as unknown as jest.Mocked<Logger>
|
||||||
|
|
||||||
const createMiddleware = () => new ValetTokenAuthMiddleware(tokenDecoder, logger)
|
const createMiddleware = () => new ValetTokenAuthMiddleware(tokenDecoder, logger)
|
||||||
@@ -222,4 +223,27 @@ describe('ValetTokenAuthMiddleware', () => {
|
|||||||
|
|
||||||
expect(next).toHaveBeenCalledWith(error)
|
expect(next).toHaveBeenCalledWith(error)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should throw an error if the valet token indicates an ongoing transition', async () => {
|
||||||
|
request.headers['x-valet-token'] = 'valet-token'
|
||||||
|
|
||||||
|
tokenDecoder.decodeToken = jest.fn().mockReturnValue({
|
||||||
|
userUuid: '1-2-3',
|
||||||
|
permittedResources: [
|
||||||
|
{
|
||||||
|
remoteIdentifier: '00000000-0000-0000-0000-000000000000',
|
||||||
|
unencryptedFileSize: 30,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
permittedOperation: 'write',
|
||||||
|
uploadBytesLimit: -1,
|
||||||
|
uploadBytesUsed: 80,
|
||||||
|
ongoingTransition: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
await createMiddleware().handler(request, response, next)
|
||||||
|
|
||||||
|
expect(response.status).toHaveBeenCalledWith(500)
|
||||||
|
expect(next).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -46,6 +46,19 @@ export class ValetTokenAuthMiddleware extends BaseMiddleware {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (valetTokenData.ongoingTransition === true) {
|
||||||
|
this.logger.error(`Cannot perform file operations for user ${valetTokenData.userUuid} during transition`)
|
||||||
|
|
||||||
|
response.status(500).send({
|
||||||
|
error: {
|
||||||
|
tag: 'ongoing-transition',
|
||||||
|
message: 'Cannot perform file operations during transition',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
for (const resource of valetTokenData.permittedResources) {
|
for (const resource of valetTokenData.permittedResources) {
|
||||||
const resourceUuidOrError = Uuid.create(resource.remoteIdentifier)
|
const resourceUuidOrError = Uuid.create(resource.remoteIdentifier)
|
||||||
if (resourceUuidOrError.isFailed()) {
|
if (resourceUuidOrError.isFailed()) {
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export class S3FileRemover implements FileRemoverInterface {
|
|||||||
fileByteSize: file.Size as number,
|
fileByteSize: file.Size as number,
|
||||||
fileName: file.Key.replace(`${userUuid}/`, ''),
|
fileName: file.Key.replace(`${userUuid}/`, ''),
|
||||||
filePath: file.Key,
|
filePath: file.Key,
|
||||||
userUuid,
|
userOrSharedVaultUuid: userUuid,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,86 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.16.27](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.26...@standardnotes/home-server@1.16.27) (2023-10-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.16.26](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.25...@standardnotes/home-server@1.16.26) (2023-10-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.16.25](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.24...@standardnotes/home-server@1.16.25) (2023-10-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.16.24](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.23...@standardnotes/home-server@1.16.24) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.16.23](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.22...@standardnotes/home-server@1.16.23) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.16.22](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.21...@standardnotes/home-server@1.16.22) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.16.21](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.20...@standardnotes/home-server@1.16.21) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.16.20](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.19...@standardnotes/home-server@1.16.20) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.16.19](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.18...@standardnotes/home-server@1.16.19) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.16.18](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.17...@standardnotes/home-server@1.16.18) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.16.17](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.16...@standardnotes/home-server@1.16.17) (2023-10-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.16.16](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.15...@standardnotes/home-server@1.16.16) (2023-10-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.16.15](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.14...@standardnotes/home-server@1.16.15) (2023-10-03)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.16.14](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.13...@standardnotes/home-server@1.16.14) (2023-10-02)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.16.13](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.12...@standardnotes/home-server@1.16.13) (2023-10-02)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.16.12](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.11...@standardnotes/home-server@1.16.12) (2023-09-29)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.16.11](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.10...@standardnotes/home-server@1.16.11) (2023-09-29)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.16.10](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.9...@standardnotes/home-server@1.16.10) (2023-09-29)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.16.9](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.8...@standardnotes/home-server@1.16.9) (2023-09-28)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.16.8](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.7...@standardnotes/home-server@1.16.8) (2023-09-27)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
## [1.16.7](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.6...@standardnotes/home-server@1.16.7) (2023-09-26)
|
## [1.16.7](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.6...@standardnotes/home-server@1.16.7) (2023-09-26)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/home-server
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/home-server",
|
"name": "@standardnotes/home-server",
|
||||||
"version": "1.16.7",
|
"version": "1.16.27",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user