mirror of
https://github.com/standardnotes/server
synced 2026-01-19 02:06:04 -05:00
Compare commits
22 Commits
@standardn
...
@standardn
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9b8d0ceb7 | ||
|
|
a2c1ebe675 | ||
|
|
3ef8e9ea24 | ||
|
|
c99334889c | ||
|
|
7ce9aba517 | ||
|
|
46257a058b | ||
|
|
979dc35cfc | ||
|
|
c99a447a04 | ||
|
|
6dd9fd5abd | ||
|
|
0d37cb293c | ||
|
|
27d04c95a1 | ||
|
|
cd830cdf25 | ||
|
|
5b06ea94f9 | ||
|
|
aba4f90485 | ||
|
|
350621ed52 | ||
|
|
69b4324c78 | ||
|
|
b2be0a7c0b | ||
|
|
cab0dfba39 | ||
|
|
296ca47d63 | ||
|
|
1cad18a681 | ||
|
|
bdd052f90c | ||
|
|
32fe8d0a85 |
6
.github/ci.env
vendored
6
.github/ci.env
vendored
@@ -23,12 +23,6 @@ MYSQL_USER=std_notes_user
|
||||
MYSQL_PASSWORD=changeme123
|
||||
MYSQL_ROOT_PASSWORD=changeme123
|
||||
|
||||
MONGO_HOST=secondary_db
|
||||
MONGO_PORT=27017
|
||||
MONGO_USERNAME=standardnotes
|
||||
MONGO_PASSWORD=standardnotes
|
||||
MONGO_DATABASE=standardnotes
|
||||
|
||||
AUTH_JWT_SECRET=f95259c5e441f5a4646d76422cfb3df4c4488842901aa50b6c51b8be2e0040e9
|
||||
AUTH_SERVER_ENCRYPTION_SERVER_KEY=1087415dfde3093797f9a7ca93a49e7d7aa1861735eb0d32aae9c303b8c3d060
|
||||
VALET_TOKEN_SECRET=4b886819ebe1e908077c6cae96311b48a8416bd60cc91c03060e15bdf6b30d1f
|
||||
|
||||
40
.github/dependabot.yml
vendored
40
.github/dependabot.yml
vendored
@@ -9,101 +9,141 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/analytics"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/api-gateway"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/auth"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/common"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/domain-core"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/domain-events"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/domain-events-infra"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/event-store"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/files"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/home-server"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/predicates"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/revisions"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/scheduler"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/security"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/settings"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/sncrypto-node"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/syncing-server"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/time"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/websockets"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
|
||||
2
.github/workflows/common-docker-image.yml
vendored
2
.github/workflows/common-docker-image.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
|
||||
11
.github/workflows/common-e2e.yml
vendored
11
.github/workflows/common-e2e.yml
vendored
@@ -11,15 +11,6 @@ on:
|
||||
type: string
|
||||
default: all
|
||||
description: The test suite to run
|
||||
secrets:
|
||||
DOCKER_USERNAME:
|
||||
required: true
|
||||
DOCKER_PASSWORD:
|
||||
required: true
|
||||
AWS_ACCESS_KEY_ID:
|
||||
required: true
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
e2e-self-hosted:
|
||||
@@ -27,11 +18,9 @@ jobs:
|
||||
with:
|
||||
snjs_image_tag: ${{ inputs.snjs_image_tag }}
|
||||
suite: ${{ inputs.suite }}
|
||||
secrets: inherit
|
||||
|
||||
e2e-home-server:
|
||||
uses: standardnotes/server/.github/workflows/e2e-home-server.yml@main
|
||||
with:
|
||||
snjs_image_tag: ${{ inputs.snjs_image_tag }}
|
||||
suite: ${{ inputs.suite }}
|
||||
secrets: inherit
|
||||
|
||||
2
.github/workflows/common-self-hosting.yml
vendored
2
.github/workflows/common-self-hosting.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
|
||||
28
.github/workflows/e2e-home-server.yml
vendored
28
.github/workflows/e2e-home-server.yml
vendored
@@ -11,15 +11,6 @@ on:
|
||||
type: string
|
||||
default: all
|
||||
description: The test suite to run
|
||||
secrets:
|
||||
DOCKER_USERNAME:
|
||||
required: true
|
||||
DOCKER_PASSWORD:
|
||||
required: true
|
||||
AWS_ACCESS_KEY_ID:
|
||||
required: true
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
e2e-home-server:
|
||||
@@ -29,7 +20,6 @@ jobs:
|
||||
matrix:
|
||||
db_type: [mysql, sqlite]
|
||||
cache_type: [redis, memory]
|
||||
secondary_db_enabled: [true, false]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -51,17 +41,9 @@ jobs:
|
||||
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
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
@@ -98,12 +80,6 @@ jobs:
|
||||
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
|
||||
|
||||
@@ -122,7 +98,7 @@ jobs:
|
||||
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 }}
|
||||
name: home-server-failure-logs-${{ inputs.suite }}-${{ matrix.db_type }}-${{ matrix.cache_type }}
|
||||
retention-days: 5
|
||||
path: |
|
||||
logs/output.log
|
||||
|
||||
16
.github/workflows/e2e-self-hosted.yml
vendored
16
.github/workflows/e2e-self-hosted.yml
vendored
@@ -11,23 +11,12 @@ on:
|
||||
type: string
|
||||
default: all
|
||||
description: The test suite to run
|
||||
secrets:
|
||||
DOCKER_USERNAME:
|
||||
required: true
|
||||
DOCKER_PASSWORD:
|
||||
required: true
|
||||
AWS_ACCESS_KEY_ID:
|
||||
required: true
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
e2e:
|
||||
name: (Self Hosting) E2E Test Suite
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
secondary_db_enabled: [true, false]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
services:
|
||||
@@ -37,7 +26,7 @@ jobs:
|
||||
- 9001:9001
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
@@ -53,7 +42,6 @@ jobs:
|
||||
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
|
||||
@@ -65,7 +53,7 @@ jobs:
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: self-hosted-failure-logs-${{ inputs.suite }}-${{ matrix.secondary_db_enabled }}
|
||||
name: self-hosted-failure-logs-${{ inputs.suite }}
|
||||
retention-days: 5
|
||||
path: |
|
||||
logs/*.err
|
||||
|
||||
1
.github/workflows/e2e-test-suite.yml
vendored
1
.github/workflows/e2e-test-suite.yml
vendored
@@ -31,4 +31,3 @@ jobs:
|
||||
with:
|
||||
snjs_image_tag: ${{ inputs.snjs_image_tag || 'latest' }}
|
||||
suite: ${{ inputs.suite || 'all' }}
|
||||
secrets: inherit
|
||||
|
||||
28
.github/workflows/pr.yml
vendored
28
.github/workflows/pr.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Install
|
||||
run: yarn install --immutable
|
||||
run: yarn install
|
||||
|
||||
- name: Build
|
||||
run: yarn build
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Install
|
||||
run: yarn install --immutable
|
||||
run: yarn install
|
||||
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
@@ -69,7 +69,7 @@ jobs:
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
@@ -86,7 +86,7 @@ jobs:
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Install
|
||||
run: yarn install --immutable
|
||||
run: yarn install
|
||||
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
@@ -102,13 +102,11 @@ jobs:
|
||||
with:
|
||||
snjs_image_tag: 'latest'
|
||||
suite: 'base'
|
||||
secrets: inherit
|
||||
|
||||
# e2e-vaults:
|
||||
# needs: build
|
||||
# name: E2E Vaults Suite
|
||||
# uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
||||
# with:
|
||||
# snjs_image_tag: 'latest'
|
||||
# suite: 'vaults'
|
||||
# secrets: inherit
|
||||
e2e-vaults:
|
||||
needs: build
|
||||
name: E2E Vaults Suite
|
||||
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
||||
with:
|
||||
snjs_image_tag: 'latest'
|
||||
suite: 'vaults'
|
||||
|
||||
24
.github/workflows/publish.yml
vendored
24
.github/workflows/publish.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
||||
if: contains(github.event.head_commit.message, 'chore(release)') == false
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
@@ -69,7 +69,7 @@ jobs:
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
@@ -102,16 +102,14 @@ jobs:
|
||||
with:
|
||||
snjs_image_tag: 'latest'
|
||||
suite: 'base'
|
||||
secrets: inherit
|
||||
|
||||
# e2e-vaults:
|
||||
# needs: build
|
||||
# name: E2E Vaults Suite
|
||||
# uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
||||
# with:
|
||||
# snjs_image_tag: 'latest'
|
||||
# suite: 'vaults'
|
||||
# secrets: inherit
|
||||
e2e-vaults:
|
||||
needs: build
|
||||
name: E2E Vaults Suite
|
||||
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
||||
with:
|
||||
snjs_image_tag: 'latest'
|
||||
suite: 'vaults'
|
||||
|
||||
publish-self-hosting:
|
||||
needs: [ test, lint, e2e-base ]
|
||||
@@ -126,7 +124,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.CI_PAT_TOKEN }}
|
||||
fetch-depth: 0
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@opentelemetry-core-npm-1.17.1-bb64066091-c0be1257b7.zip
vendored
Normal file
BIN
.yarn/cache/@opentelemetry-core-npm-1.17.1-bb64066091-c0be1257b7.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@opentelemetry-exporter-metrics-otlp-proto-npm-0.44.0-f54c7dbfa1-6a90adc5f4.zip
vendored
Normal file
BIN
.yarn/cache/@opentelemetry-exporter-metrics-otlp-proto-npm-0.44.0-f54c7dbfa1-6a90adc5f4.zip
vendored
Normal file
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.
BIN
.yarn/cache/@opentelemetry-otlp-transformer-npm-0.44.0-5745fac6a9-a22be32783.zip
vendored
Normal file
BIN
.yarn/cache/@opentelemetry-otlp-transformer-npm-0.44.0-5745fac6a9-a22be32783.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@opentelemetry-resources-npm-1.17.1-0cf263d1f6-4acd00237a.zip
vendored
Normal file
BIN
.yarn/cache/@opentelemetry-resources-npm-1.17.1-0cf263d1f6-4acd00237a.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@opentelemetry-sdk-logs-npm-0.44.0-765493a6be-f591982255.zip
vendored
Normal file
BIN
.yarn/cache/@opentelemetry-sdk-logs-npm-0.44.0-765493a6be-f591982255.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@opentelemetry-semantic-conventions-npm-1.17.1-bc0fc3b033-1abbb47c85.zip
vendored
Normal file
BIN
.yarn/cache/@opentelemetry-semantic-conventions-npm-1.17.1-bc0fc3b033-1abbb47c85.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/@types-express-npm-4.17.18-c095318854-b344988a35.zip
vendored
Normal file
BIN
.yarn/cache/@types-express-npm-4.17.18-c095318854-b344988a35.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/bson-npm-6.0.0-7b3cba060e-e7614bdc53.zip
vendored
BIN
.yarn/cache/bson-npm-6.0.0-7b3cba060e-e7614bdc53.zip
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/tr46-npm-3.0.0-e1ae1ea7c9-b09a15886c.zip
vendored
BIN
.yarn/cache/tr46-npm-3.0.0-e1ae1ea7c9-b09a15886c.zip
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -3,6 +3,8 @@ FROM node:20.6.1-alpine
|
||||
ENV NODE_ENV production
|
||||
|
||||
RUN apk add --update --no-cache \
|
||||
g++ \
|
||||
make \
|
||||
openssl \
|
||||
curl \
|
||||
bash \
|
||||
|
||||
@@ -22,7 +22,6 @@ services:
|
||||
environment:
|
||||
DB_TYPE: "${DB_TYPE}"
|
||||
CACHE_TYPE: "${CACHE_TYPE}"
|
||||
SECONDARY_DB_ENABLED: "${SECONDARY_DB_ENABLED}"
|
||||
container_name: server-ci
|
||||
ports:
|
||||
- 3123:3000
|
||||
@@ -61,21 +60,6 @@ services:
|
||||
networks:
|
||||
- standardnotes_self_hosted
|
||||
|
||||
secondary_db:
|
||||
image: mongo:5.0
|
||||
container_name: secondary_db-ci
|
||||
ports:
|
||||
- 27017
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./data/mongo:/data/db
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: standardnotes
|
||||
MONGO_INITDB_ROOT_PASSWORD: standardnotes
|
||||
MONGO_INITDB_DATABASE: standardnotes
|
||||
networks:
|
||||
- standardnotes_self_hosted
|
||||
|
||||
cache:
|
||||
image: redis:6.0-alpine
|
||||
container_name: cache-ci
|
||||
|
||||
@@ -57,9 +57,6 @@ fi
|
||||
if [ -z "$CACHE_TYPE" ]; then
|
||||
export CACHE_TYPE="redis"
|
||||
fi
|
||||
if [ -z "$SECONDARY_DB_ENABLED" ]; then
|
||||
export SECONDARY_DB_ENABLED=false
|
||||
fi
|
||||
export DB_MIGRATIONS_PATH="dist/migrations/*.js"
|
||||
|
||||
#########
|
||||
|
||||
@@ -3,6 +3,26 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.32.2](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.32.1...@standardnotes/analytics@2.32.2) (2023-10-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
## [2.32.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.32.0...@standardnotes/analytics@2.32.1) (2023-10-18)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
# [2.32.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.31.7...@standardnotes/analytics@2.32.0) (2023-10-17)
|
||||
|
||||
### Features
|
||||
|
||||
* add wrapping sqs receive message with open telemetry ([aba4f90](https://github.com/standardnotes/server/commit/aba4f90485e1b40baac34561321a5381945aa27e))
|
||||
|
||||
## [2.31.7](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.31.6...@standardnotes/analytics@2.31.7) (2023-10-13)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* reduce the amount of metrics gathered in telemetery ([32fe8d0](https://github.com/standardnotes/server/commit/32fe8d0a8523d6e1875cd0814c0cbdf27d8df7b3))
|
||||
|
||||
## [2.31.6](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.31.5...@standardnotes/analytics@2.31.6) (2023-10-12)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'reflect-metadata'
|
||||
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
|
||||
import { EmailLevel, ServiceIdentifier } from '@standardnotes/domain-core'
|
||||
|
||||
const sdk = new OpenTelemetrySDK(ServiceIdentifier.NAMES.AnalyticsScheduledTask)
|
||||
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.AnalyticsScheduledTask })
|
||||
sdk.start()
|
||||
|
||||
import { Logger } from 'winston'
|
||||
|
||||
@@ -3,11 +3,11 @@ import 'reflect-metadata'
|
||||
import { OpenTelemetrySDK } from '@standardnotes/domain-events-infra'
|
||||
import { ServiceIdentifier } from '@standardnotes/domain-core'
|
||||
|
||||
const sdk = new OpenTelemetrySDK(ServiceIdentifier.NAMES.AnalyticsWorker)
|
||||
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.AnalyticsWorker })
|
||||
sdk.start()
|
||||
|
||||
import { Logger } from 'winston'
|
||||
import { DomainEventSubscriberFactoryInterface } from '@standardnotes/domain-events'
|
||||
import { DomainEventSubscriberInterface } from '@standardnotes/domain-events'
|
||||
import * as dayjs from 'dayjs'
|
||||
import * as utc from 'dayjs/plugin/utc'
|
||||
|
||||
@@ -26,6 +26,7 @@ void container.load().then((container) => {
|
||||
|
||||
logger.info('Starting worker...')
|
||||
|
||||
const subscriberFactory: DomainEventSubscriberFactoryInterface = container.get(TYPES.DomainEventSubscriberFactory)
|
||||
subscriberFactory.create().start()
|
||||
const subscriber = container.get<DomainEventSubscriberInterface>(TYPES.DomainEventSubscriber)
|
||||
|
||||
subscriber.start()
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/analytics",
|
||||
"version": "2.31.6",
|
||||
"version": "2.32.2",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -5,9 +5,9 @@ import {
|
||||
DomainEventHandlerInterface,
|
||||
DomainEventMessageHandlerInterface,
|
||||
DomainEventPublisherInterface,
|
||||
DomainEventSubscriberFactoryInterface,
|
||||
DomainEventSubscriberInterface,
|
||||
} from '@standardnotes/domain-events'
|
||||
import { MapperInterface } from '@standardnotes/domain-core'
|
||||
import { MapperInterface, ServiceIdentifier } from '@standardnotes/domain-core'
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const Mixpanel = require('mixpanel')
|
||||
|
||||
@@ -17,8 +17,8 @@ import { AppDataSource } from './DataSource'
|
||||
import { DomainEventFactory } from '../Domain/Event/DomainEventFactory'
|
||||
import {
|
||||
SNSOpenTelemetryDomainEventPublisher,
|
||||
SQSDomainEventSubscriberFactory,
|
||||
SQSEventMessageHandler,
|
||||
SQSOpenTelemetryDomainEventSubscriber,
|
||||
} from '@standardnotes/domain-events-infra'
|
||||
import { Timer, TimerInterface } from '@standardnotes/time'
|
||||
import { PeriodKeyGeneratorInterface } from '../Domain/Time/PeriodKeyGeneratorInterface'
|
||||
@@ -240,12 +240,14 @@ export class ContainerConfigLoader {
|
||||
.bind<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler)
|
||||
.toConstantValue(new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Logger)))
|
||||
container
|
||||
.bind<DomainEventSubscriberFactoryInterface>(TYPES.DomainEventSubscriberFactory)
|
||||
.bind<DomainEventSubscriberInterface>(TYPES.DomainEventSubscriber)
|
||||
.toConstantValue(
|
||||
new SQSDomainEventSubscriberFactory(
|
||||
container.get(TYPES.SQS),
|
||||
container.get(TYPES.SQS_QUEUE_URL),
|
||||
container.get(TYPES.DomainEventMessageHandler),
|
||||
new SQSOpenTelemetryDomainEventSubscriber(
|
||||
ServiceIdentifier.NAMES.AnalyticsWorker,
|
||||
container.get<SQSClient>(TYPES.SQS),
|
||||
container.get<string>(TYPES.SQS_QUEUE_URL),
|
||||
container.get<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler),
|
||||
container.get<winston.Logger>(TYPES.Logger),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ const TYPES = {
|
||||
RevenueModificationMap: Symbol.for('RevenueModificationMap'),
|
||||
// Services
|
||||
DomainEventPublisher: Symbol.for('DomainEventPublisher'),
|
||||
DomainEventSubscriberFactory: Symbol.for('DomainEventSubscriberFactory'),
|
||||
DomainEventSubscriber: Symbol.for('DomainEventSubscriber'),
|
||||
DomainEventFactory: Symbol.for('DomainEventFactory'),
|
||||
DomainEventMessageHandler: Symbol.for('DomainEventMessageHandler'),
|
||||
AnalyticsStore: Symbol.for('AnalyticsStore'),
|
||||
|
||||
@@ -3,6 +3,26 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.80.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.79.14...@standardnotes/api-gateway@1.80.0) (2023-10-19)
|
||||
|
||||
### Features
|
||||
|
||||
* remove transition state ([#882](https://github.com/standardnotes/api-gateway/issues/882)) ([a2c1ebe](https://github.com/standardnotes/api-gateway/commit/a2c1ebe675cd5678c923715056a6966f465a15d6))
|
||||
|
||||
## [1.79.14](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.79.13...@standardnotes/api-gateway@1.79.14) (2023-10-18)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
## [1.79.13](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.79.12...@standardnotes/api-gateway@1.79.13) (2023-10-17)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
## [1.79.12](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.79.11...@standardnotes/api-gateway@1.79.12) (2023-10-13)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* reduce the amount of metrics gathered in telemetery ([32fe8d0](https://github.com/standardnotes/api-gateway/commit/32fe8d0a8523d6e1875cd0814c0cbdf27d8df7b3))
|
||||
|
||||
## [1.79.11](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.79.10...@standardnotes/api-gateway@1.79.11) (2023-10-12)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'reflect-metadata'
|
||||
import { OpenTelemetrySDK } from '@standardnotes/domain-events-infra'
|
||||
import { ServiceIdentifier } from '@standardnotes/domain-core'
|
||||
|
||||
const sdk = new OpenTelemetrySDK(ServiceIdentifier.NAMES.ApiGateway)
|
||||
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.ApiGateway })
|
||||
sdk.start()
|
||||
|
||||
import '../src/Controller/LegacyController'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/api-gateway",
|
||||
"version": "1.79.11",
|
||||
"version": "1.80.0",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -39,7 +39,7 @@ export abstract class AuthMiddleware extends BaseMiddleware {
|
||||
crossServiceToken = await this.crossServiceTokenCache.get(cacheKey)
|
||||
}
|
||||
|
||||
if (this.crossServiceTokenIsEmptyOrRequiresRevalidation(crossServiceToken)) {
|
||||
if (crossServiceToken === null) {
|
||||
const authResponse = await this.serviceProxy.validateSession({
|
||||
authorization: authHeaderValue,
|
||||
sharedVaultOwnerContext: sharedVaultOwnerContextHeaderValue,
|
||||
@@ -129,14 +129,4 @@ export abstract class AuthMiddleware extends BaseMiddleware {
|
||||
|
||||
return Math.min(crossServiceTokenDefaultCacheExpiration, sessionAccessExpiration, sessionRefreshExpiration)
|
||||
}
|
||||
|
||||
private crossServiceTokenIsEmptyOrRequiresRevalidation(crossServiceToken: string | null) {
|
||||
if (crossServiceToken === null) {
|
||||
return true
|
||||
}
|
||||
|
||||
const decodedToken = <CrossServiceTokenData>verify(crossServiceToken, this.jwtSecret, { algorithms: ['HS256'] })
|
||||
|
||||
return decodedToken.ongoing_transition === true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,16 +34,6 @@ export class ItemsController extends BaseHttpController {
|
||||
)
|
||||
}
|
||||
|
||||
@httpPost('/transition')
|
||||
async transition(request: Request, response: Response): Promise<void> {
|
||||
await this.serviceProxy.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier('POST', 'items/transition'),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
|
||||
@httpGet('/:uuid')
|
||||
async getItem(request: Request, response: Response): Promise<void> {
|
||||
await this.serviceProxy.callSyncingServer(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Request, Response } from 'express'
|
||||
import { inject } from 'inversify'
|
||||
import { BaseHttpController, controller, httpDelete, httpGet, httpPost } from 'inversify-express-utils'
|
||||
import { BaseHttpController, controller, httpDelete, httpGet } from 'inversify-express-utils'
|
||||
|
||||
import { TYPES } from '../../Bootstrap/Types'
|
||||
import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
|
||||
@@ -55,14 +55,4 @@ export class RevisionsControllerV2 extends BaseHttpController {
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@httpPost('/revisions/transition')
|
||||
async transition(request: Request, response: Response): Promise<void> {
|
||||
await this.serviceProxy.callRevisionsServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier('POST', 'revisions/transition'),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,40 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.160.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.159.2...@standardnotes/auth-server@1.160.0) (2023-10-19)
|
||||
|
||||
### Features
|
||||
|
||||
* remove transition state ([#882](https://github.com/standardnotes/server/issues/882)) ([a2c1ebe](https://github.com/standardnotes/server/commit/a2c1ebe675cd5678c923715056a6966f465a15d6))
|
||||
|
||||
## [1.159.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.159.1...@standardnotes/auth-server@1.159.2) (2023-10-18)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
## [1.159.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.159.0...@standardnotes/auth-server@1.159.1) (2023-10-17)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auth:** traversing through users in transition ([0d37cb2](https://github.com/standardnotes/server/commit/0d37cb293c3f8c1fa798a3c847a1f76c18a8c3aa))
|
||||
|
||||
# [1.159.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.158.8...@standardnotes/auth-server@1.159.0) (2023-10-17)
|
||||
|
||||
### Features
|
||||
|
||||
* add wrapping sqs receive message with open telemetry ([aba4f90](https://github.com/standardnotes/server/commit/aba4f90485e1b40baac34561321a5381945aa27e))
|
||||
|
||||
## [1.158.8](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.158.7...@standardnotes/auth-server@1.158.8) (2023-10-16)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auth:** logs for triggering transition ([1cad18a](https://github.com/standardnotes/server/commit/1cad18a681d933c67244d43dd6f3c2ec405149be))
|
||||
|
||||
## [1.158.7](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.158.6...@standardnotes/auth-server@1.158.7) (2023-10-13)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* reduce the amount of metrics gathered in telemetery ([32fe8d0](https://github.com/standardnotes/server/commit/32fe8d0a8523d6e1875cd0814c0cbdf27d8df7b3))
|
||||
|
||||
## [1.158.6](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.158.5...@standardnotes/auth-server@1.158.6) (2023-10-12)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'reflect-metadata'
|
||||
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
|
||||
import { ServiceIdentifier } from '@standardnotes/domain-core'
|
||||
|
||||
const sdk = new OpenTelemetrySDK(ServiceIdentifier.NAMES.AuthScheduledTask)
|
||||
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.AuthScheduledTask })
|
||||
sdk.start()
|
||||
|
||||
import { Stream } from 'stream'
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'reflect-metadata'
|
||||
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
|
||||
import { ServiceIdentifier } from '@standardnotes/domain-core'
|
||||
|
||||
const sdk = new OpenTelemetrySDK(ServiceIdentifier.NAMES.AuthScheduledTask)
|
||||
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.AuthScheduledTask })
|
||||
sdk.start()
|
||||
|
||||
import { Logger } from 'winston'
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'reflect-metadata'
|
||||
import { OpenTelemetrySDK } from '@standardnotes/domain-events-infra'
|
||||
import { ServiceIdentifier } from '@standardnotes/domain-core'
|
||||
|
||||
const sdk = new OpenTelemetrySDK(ServiceIdentifier.NAMES.Auth)
|
||||
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.Auth })
|
||||
sdk.start()
|
||||
|
||||
import '../src/Infra/InversifyExpressUtils/AnnotatedAuthController'
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'reflect-metadata'
|
||||
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
|
||||
import { ServiceIdentifier } from '@standardnotes/domain-core'
|
||||
|
||||
const sdk = new OpenTelemetrySDK(ServiceIdentifier.NAMES.AuthScheduledTask)
|
||||
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.AuthScheduledTask })
|
||||
sdk.start()
|
||||
|
||||
import { Logger } from 'winston'
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
|
||||
import { ServiceIdentifier, RoleName, TransitionStatus } from '@standardnotes/domain-core'
|
||||
|
||||
const sdk = new OpenTelemetrySDK(ServiceIdentifier.NAMES.AuthScheduledTask)
|
||||
sdk.start()
|
||||
|
||||
import { Logger } from 'winston'
|
||||
import * as dayjs from 'dayjs'
|
||||
import * as utc from 'dayjs/plugin/utc'
|
||||
|
||||
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
||||
import TYPES from '../src/Bootstrap/Types'
|
||||
import { Env } from '../src/Bootstrap/Env'
|
||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||
import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFactoryInterface'
|
||||
import { UserRepositoryInterface } from '../src/Domain/User/UserRepositoryInterface'
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
import { TransitionStatusRepositoryInterface } from '../src/Domain/Transition/TransitionStatusRepositoryInterface'
|
||||
|
||||
const inputArgs = process.argv.slice(2)
|
||||
const startDateString = inputArgs[0]
|
||||
const endDateString = inputArgs[1]
|
||||
const forceRunParam = inputArgs[2]
|
||||
|
||||
const requestTransition = async (
|
||||
transitionStatusRepository: TransitionStatusRepositoryInterface,
|
||||
userRepository: UserRepositoryInterface,
|
||||
logger: Logger,
|
||||
domainEventFactory: DomainEventFactoryInterface,
|
||||
domainEventPublisher: DomainEventPublisherInterface,
|
||||
timer: TimerInterface,
|
||||
): Promise<void> => {
|
||||
const startDate = new Date(startDateString)
|
||||
const endDate = new Date(endDateString)
|
||||
|
||||
const users = await userRepository.findAllCreatedBetween(startDate, endDate)
|
||||
|
||||
const timestamp = timer.getTimestampInMicroseconds()
|
||||
|
||||
logger.info(
|
||||
`[TRANSITION ${timestamp}] Found ${users.length} users created between ${startDateString} and ${endDateString}`,
|
||||
)
|
||||
|
||||
let usersTriggered = 0
|
||||
const forceRun = forceRunParam === 'true'
|
||||
for (const user of users) {
|
||||
const itemsTransitionStatus = await transitionStatusRepository.getStatus(user.uuid, 'items')
|
||||
const revisionsTransitionStatus = await transitionStatusRepository.getStatus(user.uuid, 'revisions')
|
||||
|
||||
const userRoles = await user.roles
|
||||
|
||||
const userHasTransitionRole = userRoles.some((role) => role.name === RoleName.NAMES.TransitionUser)
|
||||
const bothTransitionStatusesAreVerified =
|
||||
itemsTransitionStatus?.value === TransitionStatus.STATUSES.Verified &&
|
||||
revisionsTransitionStatus?.value === TransitionStatus.STATUSES.Verified
|
||||
|
||||
if (!userHasTransitionRole && bothTransitionStatusesAreVerified) {
|
||||
continue
|
||||
}
|
||||
|
||||
let wasTransitionRequested = false
|
||||
|
||||
if (
|
||||
itemsTransitionStatus === null ||
|
||||
itemsTransitionStatus.value === TransitionStatus.STATUSES.Failed ||
|
||||
(itemsTransitionStatus.value === TransitionStatus.STATUSES.InProgress && forceRun)
|
||||
) {
|
||||
wasTransitionRequested = true
|
||||
await transitionStatusRepository.remove(user.uuid, 'items')
|
||||
|
||||
await domainEventPublisher.publish(
|
||||
domainEventFactory.createTransitionRequestedEvent({
|
||||
userUuid: user.uuid,
|
||||
type: 'items',
|
||||
timestamp,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
if (
|
||||
revisionsTransitionStatus === null ||
|
||||
revisionsTransitionStatus.value === TransitionStatus.STATUSES.Failed ||
|
||||
(revisionsTransitionStatus.value === TransitionStatus.STATUSES.InProgress && forceRun)
|
||||
) {
|
||||
wasTransitionRequested = true
|
||||
await transitionStatusRepository.remove(user.uuid, 'revisions')
|
||||
|
||||
await domainEventPublisher.publish(
|
||||
domainEventFactory.createTransitionRequestedEvent({
|
||||
userUuid: user.uuid,
|
||||
type: 'revisions',
|
||||
timestamp,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
usersTriggered += 1
|
||||
|
||||
if (wasTransitionRequested) {
|
||||
logger.info(
|
||||
`[TRANSITION ${timestamp}] Transition requested for user ${user.uuid} - items status: ${itemsTransitionStatus?.value}, revisions status: ${revisionsTransitionStatus?.value}, has transition role: ${userHasTransitionRole}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
logger.info(
|
||||
`[TRANSITION ${timestamp}] Triggered transition for ${usersTriggered} users created between ${startDateString} and ${endDateString}`,
|
||||
)
|
||||
}
|
||||
|
||||
const container = new ContainerConfigLoader('worker')
|
||||
void container.load().then((container) => {
|
||||
dayjs.extend(utc)
|
||||
|
||||
const env: Env = new Env()
|
||||
env.load()
|
||||
|
||||
const logger: Logger = container.get(TYPES.Auth_Logger)
|
||||
|
||||
logger.info(`Starting transition request for users created between ${startDateString} and ${endDateString}`)
|
||||
|
||||
const userRepository: UserRepositoryInterface = container.get(TYPES.Auth_UserRepository)
|
||||
const domainEventFactory: DomainEventFactoryInterface = container.get(TYPES.Auth_DomainEventFactory)
|
||||
const domainEventPublisher: DomainEventPublisherInterface = container.get(TYPES.Auth_DomainEventPublisher)
|
||||
const timer = container.get<TimerInterface>(TYPES.Auth_Timer)
|
||||
const transitionStatusRepository = container.get<TransitionStatusRepositoryInterface>(
|
||||
TYPES.Auth_TransitionStatusRepository,
|
||||
)
|
||||
|
||||
const tracer = new OpenTelemetryTracer()
|
||||
tracer.startSpan(ServiceIdentifier.NAMES.AuthScheduledTask, 'transition')
|
||||
|
||||
Promise.resolve(
|
||||
requestTransition(
|
||||
transitionStatusRepository,
|
||||
userRepository,
|
||||
logger,
|
||||
domainEventFactory,
|
||||
domainEventPublisher,
|
||||
timer,
|
||||
),
|
||||
)
|
||||
.then(() => {
|
||||
logger.info(`Finished transition request for users created between ${startDateString} and ${endDateString}`)
|
||||
|
||||
tracer.stopSpan()
|
||||
|
||||
process.exit(0)
|
||||
})
|
||||
.catch((error) => {
|
||||
logger.error(
|
||||
`Error while requesting transition for users created between ${startDateString} and ${endDateString}: ${error}`,
|
||||
)
|
||||
|
||||
tracer.stopSpanWithError(error)
|
||||
|
||||
process.exit(1)
|
||||
})
|
||||
})
|
||||
@@ -3,7 +3,7 @@ import 'reflect-metadata'
|
||||
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
|
||||
import { Email, ServiceIdentifier } from '@standardnotes/domain-core'
|
||||
|
||||
const sdk = new OpenTelemetrySDK(ServiceIdentifier.NAMES.AuthScheduledTask)
|
||||
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.AuthScheduledTask })
|
||||
sdk.start()
|
||||
|
||||
import { Logger } from 'winston'
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'reflect-metadata'
|
||||
import { OpenTelemetrySDK } from '@standardnotes/domain-events-infra'
|
||||
import { ServiceIdentifier } from '@standardnotes/domain-core'
|
||||
|
||||
const sdk = new OpenTelemetrySDK(ServiceIdentifier.NAMES.AuthWorker)
|
||||
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.AuthWorker })
|
||||
sdk.start()
|
||||
|
||||
import { Logger } from 'winston'
|
||||
@@ -11,7 +11,7 @@ import { Logger } from 'winston'
|
||||
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
||||
import TYPES from '../src/Bootstrap/Types'
|
||||
import { Env } from '../src/Bootstrap/Env'
|
||||
import { DomainEventSubscriberFactoryInterface } from '@standardnotes/domain-events'
|
||||
import { DomainEventSubscriberInterface } from '@standardnotes/domain-events'
|
||||
import * as dayjs from 'dayjs'
|
||||
import * as utc from 'dayjs/plugin/utc'
|
||||
|
||||
@@ -26,8 +26,7 @@ void container.load().then((container) => {
|
||||
|
||||
logger.info('Starting worker...')
|
||||
|
||||
const subscriberFactory: DomainEventSubscriberFactoryInterface = container.get(
|
||||
TYPES.Auth_DomainEventSubscriberFactory,
|
||||
)
|
||||
subscriberFactory.create().start()
|
||||
const subscriber = container.get<DomainEventSubscriberInterface>(TYPES.Auth_DomainEventSubscriber)
|
||||
|
||||
subscriber.start()
|
||||
})
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const path = require('path')
|
||||
|
||||
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||
|
||||
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/transition.js')))
|
||||
|
||||
Object.defineProperty(exports, '__esModule', { value: true })
|
||||
|
||||
exports.default = index
|
||||
@@ -55,13 +55,6 @@ case "$COMMAND" in
|
||||
node docker/entrypoint-backup.js one_drive daily
|
||||
;;
|
||||
|
||||
'transition' )
|
||||
START_DATE=$1 && shift 1
|
||||
END_DATE=$1 && shift 1
|
||||
echo "[Docker] Starting Transition..."
|
||||
node docker/entrypoint-transition.js $START_DATE $END_DATE
|
||||
;;
|
||||
|
||||
* )
|
||||
echo "[Docker] Unknown command"
|
||||
;;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class RemoveTransitionRole1697704066569 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DELETE FROM `roles` WHERE name = "TRANSITION_USER"')
|
||||
}
|
||||
|
||||
public async down(): Promise<void> {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/auth-server",
|
||||
"version": "1.158.6",
|
||||
"version": "1.160.0",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
DomainEventHandlerInterface,
|
||||
DomainEventMessageHandlerInterface,
|
||||
DomainEventPublisherInterface,
|
||||
DomainEventSubscriberFactoryInterface,
|
||||
DomainEventSubscriberInterface,
|
||||
} from '@standardnotes/domain-events'
|
||||
import { TimerInterface, Timer } from '@standardnotes/time'
|
||||
import { UAParser } from 'ua-parser-js'
|
||||
@@ -90,8 +90,8 @@ import {
|
||||
DirectCallDomainEventPublisher,
|
||||
DirectCallEventMessageHandler,
|
||||
SNSOpenTelemetryDomainEventPublisher,
|
||||
SQSDomainEventSubscriberFactory,
|
||||
SQSEventMessageHandler,
|
||||
SQSOpenTelemetryDomainEventSubscriber,
|
||||
} from '@standardnotes/domain-events-infra'
|
||||
import { GetUserSubscription } from '../Domain/UseCase/GetUserSubscription/GetUserSubscription'
|
||||
import { ChangeCredentials } from '../Domain/UseCase/ChangeCredentials/ChangeCredentials'
|
||||
@@ -188,6 +188,7 @@ import {
|
||||
ControllerContainer,
|
||||
ControllerContainerInterface,
|
||||
MapperInterface,
|
||||
ServiceIdentifier,
|
||||
SharedVaultUser,
|
||||
} from '@standardnotes/domain-core'
|
||||
import { SessionTracePersistenceMapper } from '../Mapping/SessionTracePersistenceMapper'
|
||||
@@ -257,11 +258,6 @@ import { UpdateStorageQuotaUsedForUser } from '../Domain/UseCase/UpdateStorageQu
|
||||
import { SharedVaultFileUploadedEventHandler } from '../Domain/Handler/SharedVaultFileUploadedEventHandler'
|
||||
import { SharedVaultFileRemovedEventHandler } from '../Domain/Handler/SharedVaultFileRemovedEventHandler'
|
||||
import { SharedVaultFileMovedEventHandler } from '../Domain/Handler/SharedVaultFileMovedEventHandler'
|
||||
import { TransitionStatusRepositoryInterface } from '../Domain/Transition/TransitionStatusRepositoryInterface'
|
||||
import { RedisTransitionStatusRepository } from '../Infra/Redis/RedisTransitionStatusRepository'
|
||||
import { InMemoryTransitionStatusRepository } from '../Infra/InMemory/InMemoryTransitionStatusRepository'
|
||||
import { TransitionStatusUpdatedEventHandler } from '../Domain/Handler/TransitionStatusUpdatedEventHandler'
|
||||
import { UpdateTransitionStatus } from '../Domain/UseCase/UpdateTransitionStatus/UpdateTransitionStatus'
|
||||
import { TypeORMSharedVaultUser } from '../Infra/TypeORM/TypeORMSharedVaultUser'
|
||||
import { SharedVaultUserPersistenceMapper } from '../Mapping/SharedVaultUserPersistenceMapper'
|
||||
import { SharedVaultUserRepositoryInterface } from '../Domain/SharedVault/SharedVaultUserRepositoryInterface'
|
||||
@@ -644,9 +640,6 @@ export class ContainerConfigLoader {
|
||||
container.get(TYPES.Auth_Timer),
|
||||
),
|
||||
)
|
||||
container
|
||||
.bind<TransitionStatusRepositoryInterface>(TYPES.Auth_TransitionStatusRepository)
|
||||
.toConstantValue(new InMemoryTransitionStatusRepository())
|
||||
} else {
|
||||
container.bind<PKCERepositoryInterface>(TYPES.Auth_PKCERepository).to(RedisPKCERepository)
|
||||
container.bind<LockRepositoryInterface>(TYPES.Auth_LockRepository).to(LockRepository)
|
||||
@@ -659,9 +652,6 @@ export class ContainerConfigLoader {
|
||||
container
|
||||
.bind<SubscriptionTokenRepositoryInterface>(TYPES.Auth_SubscriptionTokenRepository)
|
||||
.to(RedisSubscriptionTokenRepository)
|
||||
container
|
||||
.bind<TransitionStatusRepositoryInterface>(TYPES.Auth_TransitionStatusRepository)
|
||||
.toConstantValue(new RedisTransitionStatusRepository(container.get<Redis>(TYPES.Auth_Redis)))
|
||||
}
|
||||
|
||||
// Services
|
||||
@@ -984,15 +974,6 @@ export class ContainerConfigLoader {
|
||||
container.get(TYPES.Auth_SubscriptionSettingService),
|
||||
),
|
||||
)
|
||||
container
|
||||
.bind<UpdateTransitionStatus>(TYPES.Auth_UpdateTransitionStatus)
|
||||
.toConstantValue(
|
||||
new UpdateTransitionStatus(
|
||||
container.get<TransitionStatusRepositoryInterface>(TYPES.Auth_TransitionStatusRepository),
|
||||
container.get<RoleServiceInterface>(TYPES.Auth_RoleService),
|
||||
container.get<winston.Logger>(TYPES.Auth_Logger),
|
||||
),
|
||||
)
|
||||
container
|
||||
.bind<AddSharedVaultUser>(TYPES.Auth_AddSharedVaultUser)
|
||||
.toConstantValue(
|
||||
@@ -1173,14 +1154,6 @@ export class ContainerConfigLoader {
|
||||
container.get(TYPES.Auth_Logger),
|
||||
),
|
||||
)
|
||||
container
|
||||
.bind<TransitionStatusUpdatedEventHandler>(TYPES.Auth_TransitionStatusUpdatedEventHandler)
|
||||
.toConstantValue(
|
||||
new TransitionStatusUpdatedEventHandler(
|
||||
container.get<UpdateTransitionStatus>(TYPES.Auth_UpdateTransitionStatus),
|
||||
container.get<winston.Logger>(TYPES.Auth_Logger),
|
||||
),
|
||||
)
|
||||
container
|
||||
.bind<UserAddedToSharedVaultEventHandler>(TYPES.Auth_UserAddedToSharedVaultEventHandler)
|
||||
.toConstantValue(
|
||||
@@ -1238,7 +1211,6 @@ export class ContainerConfigLoader {
|
||||
['PREDICATE_VERIFICATION_REQUESTED', container.get(TYPES.Auth_PredicateVerificationRequestedEventHandler)],
|
||||
['EMAIL_SUBSCRIPTION_UNSUBSCRIBED', container.get(TYPES.Auth_EmailSubscriptionUnsubscribedEventHandler)],
|
||||
['PAYMENTS_ACCOUNT_DELETED', container.get(TYPES.Auth_PaymentsAccountDeletedEventHandler)],
|
||||
['TRANSITION_STATUS_UPDATED', container.get(TYPES.Auth_TransitionStatusUpdatedEventHandler)],
|
||||
['USER_ADDED_TO_SHARED_VAULT', container.get(TYPES.Auth_UserAddedToSharedVaultEventHandler)],
|
||||
['USER_REMOVED_FROM_SHARED_VAULT', container.get(TYPES.Auth_UserRemovedFromSharedVaultEventHandler)],
|
||||
[
|
||||
@@ -1262,12 +1234,14 @@ export class ContainerConfigLoader {
|
||||
.toConstantValue(new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Auth_Logger)))
|
||||
|
||||
container
|
||||
.bind<DomainEventSubscriberFactoryInterface>(TYPES.Auth_DomainEventSubscriberFactory)
|
||||
.bind<DomainEventSubscriberInterface>(TYPES.Auth_DomainEventSubscriber)
|
||||
.toConstantValue(
|
||||
new SQSDomainEventSubscriberFactory(
|
||||
container.get(TYPES.Auth_SQS),
|
||||
container.get(TYPES.Auth_SQS_QUEUE_URL),
|
||||
container.get(TYPES.Auth_DomainEventMessageHandler),
|
||||
new SQSOpenTelemetryDomainEventSubscriber(
|
||||
ServiceIdentifier.NAMES.AuthWorker,
|
||||
container.get<SQSClient>(TYPES.Auth_SQS),
|
||||
container.get<string>(TYPES.Auth_SQS_QUEUE_URL),
|
||||
container.get<DomainEventMessageHandlerInterface>(TYPES.Auth_DomainEventMessageHandler),
|
||||
container.get<winston.Logger>(TYPES.Auth_Logger),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ const TYPES = {
|
||||
Auth_AuthenticatorRepository: Symbol.for('Auth_AuthenticatorRepository'),
|
||||
Auth_AuthenticatorChallengeRepository: Symbol.for('Auth_AuthenticatorChallengeRepository'),
|
||||
Auth_CacheEntryRepository: Symbol.for('Auth_CacheEntryRepository'),
|
||||
Auth_TransitionStatusRepository: Symbol.for('Auth_TransitionStatusRepository'),
|
||||
Auth_SharedVaultUserRepository: Symbol.for('Auth_SharedVaultUserRepository'),
|
||||
// ORM
|
||||
Auth_ORMOfflineSettingRepository: Symbol.for('Auth_ORMOfflineSettingRepository'),
|
||||
@@ -157,7 +156,6 @@ const TYPES = {
|
||||
Auth_SignInWithRecoveryCodes: Symbol.for('Auth_SignInWithRecoveryCodes'),
|
||||
Auth_GetUserKeyParamsRecovery: Symbol.for('Auth_GetUserKeyParamsRecovery'),
|
||||
Auth_UpdateStorageQuotaUsedForUser: Symbol.for('Auth_UpdateStorageQuotaUsedForUser'),
|
||||
Auth_UpdateTransitionStatus: Symbol.for('Auth_UpdateTransitionStatus'),
|
||||
Auth_AddSharedVaultUser: Symbol.for('Auth_AddSharedVaultUser'),
|
||||
Auth_RemoveSharedVaultUser: Symbol.for('Auth_RemoveSharedVaultUser'),
|
||||
Auth_DesignateSurvivor: Symbol.for('Auth_DesignateSurvivor'),
|
||||
@@ -190,7 +188,6 @@ const TYPES = {
|
||||
Auth_PredicateVerificationRequestedEventHandler: Symbol.for('Auth_PredicateVerificationRequestedEventHandler'),
|
||||
Auth_EmailSubscriptionUnsubscribedEventHandler: Symbol.for('Auth_EmailSubscriptionUnsubscribedEventHandler'),
|
||||
Auth_PaymentsAccountDeletedEventHandler: Symbol.for('Auth_PaymentsAccountDeletedEventHandler'),
|
||||
Auth_TransitionStatusUpdatedEventHandler: Symbol.for('Auth_TransitionStatusUpdatedEventHandler'),
|
||||
Auth_UserAddedToSharedVaultEventHandler: Symbol.for('Auth_UserAddedToSharedVaultEventHandler'),
|
||||
Auth_UserRemovedFromSharedVaultEventHandler: Symbol.for('Auth_UserRemovedFromSharedVaultEventHandler'),
|
||||
Auth_UserDesignatedAsSurvivorInSharedVaultEventHandler: Symbol.for(
|
||||
@@ -218,7 +215,7 @@ const TYPES = {
|
||||
Auth_WebSocketConnectionTokenDecoder: Symbol.for('Auth_WebSocketConnectionTokenDecoder'),
|
||||
Auth_AuthenticationMethodResolver: Symbol.for('Auth_AuthenticationMethodResolver'),
|
||||
Auth_DomainEventPublisher: Symbol.for('Auth_DomainEventPublisher'),
|
||||
Auth_DomainEventSubscriberFactory: Symbol.for('Auth_DomainEventSubscriberFactory'),
|
||||
Auth_DomainEventSubscriber: Symbol.for('Auth_DomainEventSubscriber'),
|
||||
Auth_DomainEventFactory: Symbol.for('Auth_DomainEventFactory'),
|
||||
Auth_DomainEventMessageHandler: Symbol.for('Auth_DomainEventMessageHandler'),
|
||||
Auth_HTTPClient: Symbol.for('Auth_HTTPClient'),
|
||||
|
||||
@@ -20,7 +20,6 @@ import {
|
||||
StatisticPersistenceRequestedEvent,
|
||||
SessionCreatedEvent,
|
||||
SessionRefreshedEvent,
|
||||
TransitionRequestedEvent,
|
||||
} from '@standardnotes/domain-events'
|
||||
import { Predicate, PredicateVerificationResult } from '@standardnotes/predicates'
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
@@ -34,25 +33,6 @@ import { KeyParamsData } from '@standardnotes/responses'
|
||||
export class DomainEventFactory implements DomainEventFactoryInterface {
|
||||
constructor(@inject(TYPES.Auth_Timer) private timer: TimerInterface) {}
|
||||
|
||||
createTransitionRequestedEvent(dto: {
|
||||
userUuid: string
|
||||
type: 'items' | 'revisions'
|
||||
timestamp: number
|
||||
}): TransitionRequestedEvent {
|
||||
return {
|
||||
type: 'TRANSITION_REQUESTED',
|
||||
createdAt: this.timer.getUTCDate(),
|
||||
meta: {
|
||||
correlation: {
|
||||
userIdentifier: dto.userUuid,
|
||||
userIdentifierType: 'uuid',
|
||||
},
|
||||
origin: DomainEventService.Auth,
|
||||
},
|
||||
payload: dto,
|
||||
}
|
||||
}
|
||||
|
||||
createSessionCreatedEvent(dto: { userUuid: string }): SessionCreatedEvent {
|
||||
return {
|
||||
type: 'SESSION_CREATED',
|
||||
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
StatisticPersistenceRequestedEvent,
|
||||
SessionCreatedEvent,
|
||||
SessionRefreshedEvent,
|
||||
TransitionRequestedEvent,
|
||||
} from '@standardnotes/domain-events'
|
||||
import { InviteeIdentifierType } from '../SharedSubscription/InviteeIdentifierType'
|
||||
import { KeyParamsData } from '@standardnotes/responses'
|
||||
@@ -92,9 +91,4 @@ export interface DomainEventFactoryInterface {
|
||||
}): StatisticPersistenceRequestedEvent
|
||||
createSessionCreatedEvent(dto: { userUuid: string }): SessionCreatedEvent
|
||||
createSessionRefreshedEvent(dto: { userUuid: string }): SessionRefreshedEvent
|
||||
createTransitionRequestedEvent(dto: {
|
||||
userUuid: string
|
||||
type: 'items' | 'revisions'
|
||||
timestamp: number
|
||||
}): TransitionRequestedEvent
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import { DomainEventHandlerInterface, TransitionStatusUpdatedEvent } from '@standardnotes/domain-events'
|
||||
import { UpdateTransitionStatus } from '../UseCase/UpdateTransitionStatus/UpdateTransitionStatus'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
export class TransitionStatusUpdatedEventHandler implements DomainEventHandlerInterface {
|
||||
constructor(
|
||||
private updateTransitionStatusUseCase: UpdateTransitionStatus,
|
||||
private logger: Logger,
|
||||
) {}
|
||||
|
||||
async handle(event: TransitionStatusUpdatedEvent): Promise<void> {
|
||||
const result = await this.updateTransitionStatusUseCase.execute({
|
||||
status: event.payload.status,
|
||||
userUuid: event.payload.userUuid,
|
||||
transitionType: event.payload.transitionType,
|
||||
transitionTimestamp: event.payload.transitionTimestamp,
|
||||
})
|
||||
|
||||
if (result.isFailed()) {
|
||||
this.logger.error(`Failed to update transition status for user ${event.payload.userUuid}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { TransitionStatus } from '@standardnotes/domain-core'
|
||||
|
||||
export interface TransitionStatusRepositoryInterface {
|
||||
updateStatus(userUuid: string, transitionType: 'items' | 'revisions', status: TransitionStatus): Promise<void>
|
||||
getStatus(userUuid: string, transitionType: 'items' | 'revisions'): Promise<TransitionStatus | null>
|
||||
remove(userUuid: string, transitionType: 'items' | 'revisions'): Promise<void>
|
||||
}
|
||||
@@ -9,15 +9,7 @@ import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
|
||||
|
||||
import { CreateCrossServiceToken } from './CreateCrossServiceToken'
|
||||
import { GetSetting } from '../GetSetting/GetSetting'
|
||||
import {
|
||||
Result,
|
||||
SharedVaultUser,
|
||||
SharedVaultUserPermission,
|
||||
Timestamps,
|
||||
TransitionStatus,
|
||||
Uuid,
|
||||
} from '@standardnotes/domain-core'
|
||||
import { TransitionStatusRepositoryInterface } from '../../Transition/TransitionStatusRepositoryInterface'
|
||||
import { Result, SharedVaultUser, SharedVaultUserPermission, Timestamps, Uuid } from '@standardnotes/domain-core'
|
||||
import { SharedVaultUserRepositoryInterface } from '../../SharedVault/SharedVaultUserRepositoryInterface'
|
||||
|
||||
describe('CreateCrossServiceToken', () => {
|
||||
@@ -27,7 +19,6 @@ describe('CreateCrossServiceToken', () => {
|
||||
let tokenEncoder: TokenEncoderInterface<CrossServiceTokenData>
|
||||
let userRepository: UserRepositoryInterface
|
||||
let getSettingUseCase: GetSetting
|
||||
let transitionStatusRepository: TransitionStatusRepositoryInterface
|
||||
let sharedVaultUserRepository: SharedVaultUserRepositoryInterface
|
||||
const jwtTTL = 60
|
||||
|
||||
@@ -44,7 +35,6 @@ describe('CreateCrossServiceToken', () => {
|
||||
userRepository,
|
||||
jwtTTL,
|
||||
getSettingUseCase,
|
||||
transitionStatusRepository,
|
||||
sharedVaultUserRepository,
|
||||
)
|
||||
|
||||
@@ -78,11 +68,6 @@ describe('CreateCrossServiceToken', () => {
|
||||
getSettingUseCase = {} as jest.Mocked<GetSetting>
|
||||
getSettingUseCase.execute = jest.fn().mockReturnValue(Result.ok({ setting: { value: '100' } }))
|
||||
|
||||
transitionStatusRepository = {} as jest.Mocked<TransitionStatusRepositoryInterface>
|
||||
transitionStatusRepository.getStatus = jest
|
||||
.fn()
|
||||
.mockReturnValue(TransitionStatus.create(TransitionStatus.STATUSES.Verified).getValue())
|
||||
|
||||
sharedVaultUserRepository = {} as jest.Mocked<SharedVaultUserRepositoryInterface>
|
||||
sharedVaultUserRepository.findByUserUuid = jest.fn().mockReturnValue([
|
||||
SharedVaultUser.create({
|
||||
@@ -122,46 +107,6 @@ describe('CreateCrossServiceToken', () => {
|
||||
email: 'test@test.te',
|
||||
uuid: '00000000-0000-0000-0000-000000000000',
|
||||
},
|
||||
ongoing_transition: false,
|
||||
ongoing_revisions_transition: false,
|
||||
},
|
||||
60,
|
||||
)
|
||||
})
|
||||
|
||||
it('should create a cross service token for user that has an ongoing transaction', async () => {
|
||||
transitionStatusRepository.getStatus = jest
|
||||
.fn()
|
||||
.mockReturnValue(TransitionStatus.create(TransitionStatus.STATUSES.InProgress).getValue())
|
||||
|
||||
await createUseCase().execute({
|
||||
user,
|
||||
session,
|
||||
})
|
||||
|
||||
expect(tokenEncoder.encodeExpirableToken).toHaveBeenCalledWith(
|
||||
{
|
||||
roles: [
|
||||
{
|
||||
name: 'role1',
|
||||
uuid: '1-3-4',
|
||||
},
|
||||
],
|
||||
belongs_to_shared_vaults: [
|
||||
{
|
||||
shared_vault_uuid: '00000000-0000-0000-0000-000000000000',
|
||||
permission: 'read',
|
||||
},
|
||||
],
|
||||
session: {
|
||||
test: 'test',
|
||||
},
|
||||
user: {
|
||||
email: 'test@test.te',
|
||||
uuid: '00000000-0000-0000-0000-000000000000',
|
||||
},
|
||||
ongoing_transition: true,
|
||||
ongoing_revisions_transition: true,
|
||||
},
|
||||
60,
|
||||
)
|
||||
@@ -190,8 +135,6 @@ describe('CreateCrossServiceToken', () => {
|
||||
email: 'test@test.te',
|
||||
uuid: '00000000-0000-0000-0000-000000000000',
|
||||
},
|
||||
ongoing_transition: false,
|
||||
ongoing_revisions_transition: false,
|
||||
},
|
||||
60,
|
||||
)
|
||||
@@ -220,8 +163,6 @@ describe('CreateCrossServiceToken', () => {
|
||||
email: 'test@test.te',
|
||||
uuid: '00000000-0000-0000-0000-000000000000',
|
||||
},
|
||||
ongoing_transition: false,
|
||||
ongoing_revisions_transition: false,
|
||||
},
|
||||
60,
|
||||
)
|
||||
@@ -277,8 +218,6 @@ describe('CreateCrossServiceToken', () => {
|
||||
email: 'test@test.te',
|
||||
uuid: '00000000-0000-0000-0000-000000000000',
|
||||
},
|
||||
ongoing_revisions_transition: false,
|
||||
ongoing_transition: false,
|
||||
},
|
||||
60,
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { TokenEncoderInterface, CrossServiceTokenData } from '@standardnotes/security'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { Result, TransitionStatus, UseCaseInterface, Uuid } from '@standardnotes/domain-core'
|
||||
import { Result, UseCaseInterface, Uuid } from '@standardnotes/domain-core'
|
||||
|
||||
import TYPES from '../../../Bootstrap/Types'
|
||||
import { ProjectorInterface } from '../../../Projection/ProjectorInterface'
|
||||
@@ -12,7 +12,6 @@ import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
|
||||
import { CreateCrossServiceTokenDTO } from './CreateCrossServiceTokenDTO'
|
||||
import { GetSetting } from '../GetSetting/GetSetting'
|
||||
import { SettingName } from '@standardnotes/settings'
|
||||
import { TransitionStatusRepositoryInterface } from '../../Transition/TransitionStatusRepositoryInterface'
|
||||
import { SharedVaultUserRepositoryInterface } from '../../SharedVault/SharedVaultUserRepositoryInterface'
|
||||
|
||||
@injectable()
|
||||
@@ -26,8 +25,6 @@ export class CreateCrossServiceToken implements UseCaseInterface<string> {
|
||||
@inject(TYPES.Auth_AUTH_JWT_TTL) private jwtTTL: number,
|
||||
@inject(TYPES.Auth_GetSetting)
|
||||
private getSettingUseCase: GetSetting,
|
||||
@inject(TYPES.Auth_TransitionStatusRepository)
|
||||
private transitionStatusRepository: TransitionStatusRepositoryInterface,
|
||||
@inject(TYPES.Auth_SharedVaultUserRepository) private sharedVaultUserRepository: SharedVaultUserRepositoryInterface,
|
||||
) {}
|
||||
|
||||
@@ -47,9 +44,6 @@ export class CreateCrossServiceToken implements UseCaseInterface<string> {
|
||||
return Result.fail(`Could not find user with uuid ${dto.userUuid}`)
|
||||
}
|
||||
|
||||
const transitionStatus = await this.transitionStatusRepository.getStatus(user.uuid, 'items')
|
||||
const revisionsTransitionStatus = await this.transitionStatusRepository.getStatus(user.uuid, 'revisions')
|
||||
|
||||
const roles = await user.roles
|
||||
|
||||
const sharedVaultAssociations = await this.sharedVaultUserRepository.findByUserUuid(
|
||||
@@ -60,8 +54,6 @@ export class CreateCrossServiceToken implements UseCaseInterface<string> {
|
||||
user: this.projectUser(user),
|
||||
roles: this.projectRoles(roles),
|
||||
shared_vault_owner_context: undefined,
|
||||
ongoing_transition: transitionStatus?.value === TransitionStatus.STATUSES.InProgress,
|
||||
ongoing_revisions_transition: revisionsTransitionStatus?.value === TransitionStatus.STATUSES.InProgress,
|
||||
belongs_to_shared_vaults: sharedVaultAssociations.map((association) => ({
|
||||
shared_vault_uuid: association.props.sharedVaultUuid.value,
|
||||
permission: association.props.permission.value,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { TransitionStatus } from '@standardnotes/domain-core'
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
import { TokenEncoderInterface, ValetTokenData, ValetTokenOperation } from '@standardnotes/security'
|
||||
|
||||
@@ -11,7 +10,6 @@ import { User } from '../../User/User'
|
||||
import { UserSubscriptionType } from '../../Subscription/UserSubscriptionType'
|
||||
import { SubscriptionSettingsAssociationServiceInterface } from '../../Setting/SubscriptionSettingsAssociationServiceInterface'
|
||||
import { UserSubscriptionServiceInterface } from '../../Subscription/UserSubscriptionServiceInterface'
|
||||
import { TransitionStatusRepositoryInterface } from '../../Transition/TransitionStatusRepositoryInterface'
|
||||
|
||||
describe('CreateValetToken', () => {
|
||||
let tokenEncoder: TokenEncoderInterface<ValetTokenData>
|
||||
@@ -23,7 +21,6 @@ describe('CreateValetToken', () => {
|
||||
let regularSubscription: UserSubscription
|
||||
let sharedSubscription: UserSubscription
|
||||
let user: User
|
||||
let transitionStatusRepository: TransitionStatusRepositoryInterface
|
||||
|
||||
const createUseCase = () =>
|
||||
new CreateValetToken(
|
||||
@@ -33,7 +30,6 @@ describe('CreateValetToken', () => {
|
||||
userSubscriptionService,
|
||||
timer,
|
||||
valetTokenTTL,
|
||||
transitionStatusRepository,
|
||||
)
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -71,11 +67,6 @@ describe('CreateValetToken', () => {
|
||||
|
||||
timer = {} as jest.Mocked<TimerInterface>
|
||||
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 () => {
|
||||
@@ -176,7 +167,6 @@ describe('CreateValetToken', () => {
|
||||
{
|
||||
sharedSubscriptionUuid: undefined,
|
||||
regularSubscriptionUuid: '1-2-3',
|
||||
ongoingTransition: false,
|
||||
permittedOperation: 'write',
|
||||
permittedResources: [
|
||||
{
|
||||
@@ -217,7 +207,6 @@ describe('CreateValetToken', () => {
|
||||
{
|
||||
sharedSubscriptionUuid: '2-3-4',
|
||||
regularSubscriptionUuid: '1-2-3',
|
||||
ongoingTransition: false,
|
||||
permittedOperation: 'write',
|
||||
permittedResources: [
|
||||
{
|
||||
@@ -278,7 +267,6 @@ describe('CreateValetToken', () => {
|
||||
{
|
||||
sharedSubscriptionUuid: undefined,
|
||||
regularSubscriptionUuid: '1-2-3',
|
||||
ongoingTransition: false,
|
||||
permittedOperation: 'write',
|
||||
permittedResources: [
|
||||
{
|
||||
|
||||
@@ -13,8 +13,6 @@ import { CreateValetTokenDTO } from './CreateValetTokenDTO'
|
||||
import { SubscriptionSettingsAssociationServiceInterface } from '../../Setting/SubscriptionSettingsAssociationServiceInterface'
|
||||
import { UserSubscriptionServiceInterface } from '../../Subscription/UserSubscriptionServiceInterface'
|
||||
import { CreateValetTokenPayload } from '../../ValetToken/CreateValetTokenPayload'
|
||||
import { TransitionStatusRepositoryInterface } from '../../Transition/TransitionStatusRepositoryInterface'
|
||||
import { TransitionStatus } from '@standardnotes/domain-core'
|
||||
|
||||
@injectable()
|
||||
export class CreateValetToken implements UseCaseInterface {
|
||||
@@ -27,8 +25,6 @@ export class CreateValetToken implements UseCaseInterface {
|
||||
@inject(TYPES.Auth_UserSubscriptionService) private userSubscriptionService: UserSubscriptionServiceInterface,
|
||||
@inject(TYPES.Auth_Timer) private timer: TimerInterface,
|
||||
@inject(TYPES.Auth_VALET_TOKEN_TTL) private valetTokenTTL: number,
|
||||
@inject(TYPES.Auth_TransitionStatusRepository)
|
||||
private transitionStatusRepository: TransitionStatusRepositoryInterface,
|
||||
) {}
|
||||
|
||||
async execute(dto: CreateValetTokenDTO): Promise<CreateValetTokenResponseData> {
|
||||
@@ -87,8 +83,6 @@ export class CreateValetToken implements UseCaseInterface {
|
||||
sharedSubscriptionUuid = sharedSubscription.uuid
|
||||
}
|
||||
|
||||
const transitionStatus = await this.transitionStatusRepository.getStatus(userUuid, 'items')
|
||||
|
||||
const tokenData: ValetTokenData = {
|
||||
userUuid: dto.userUuid,
|
||||
permittedOperation: dto.operation,
|
||||
@@ -97,7 +91,6 @@ export class CreateValetToken implements UseCaseInterface {
|
||||
uploadBytesLimit,
|
||||
sharedSubscriptionUuid,
|
||||
regularSubscriptionUuid: regularSubscription.uuid,
|
||||
ongoingTransition: transitionStatus?.value === TransitionStatus.STATUSES.InProgress,
|
||||
}
|
||||
|
||||
const valetToken = this.tokenEncoder.encodeExpirableToken(tokenData, this.valetTokenTTL)
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
import { RoleName, TransitionStatus, Uuid } from '@standardnotes/domain-core'
|
||||
|
||||
import { RoleServiceInterface } from '../../Role/RoleServiceInterface'
|
||||
import { TransitionStatusRepositoryInterface } from '../../Transition/TransitionStatusRepositoryInterface'
|
||||
import { UpdateTransitionStatus } from './UpdateTransitionStatus'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
describe('UpdateTransitionStatus', () => {
|
||||
let transitionStatusRepository: TransitionStatusRepositoryInterface
|
||||
let roleService: RoleServiceInterface
|
||||
let logger: Logger
|
||||
|
||||
const createUseCase = () => new UpdateTransitionStatus(transitionStatusRepository, roleService, logger)
|
||||
|
||||
beforeEach(() => {
|
||||
logger = {} as jest.Mocked<Logger>
|
||||
logger.info = jest.fn()
|
||||
|
||||
transitionStatusRepository = {} as jest.Mocked<TransitionStatusRepositoryInterface>
|
||||
transitionStatusRepository.updateStatus = jest.fn()
|
||||
transitionStatusRepository.getStatus = jest.fn().mockResolvedValue(null)
|
||||
|
||||
roleService = {} as jest.Mocked<RoleServiceInterface>
|
||||
roleService.removeRoleFromUser = jest.fn()
|
||||
})
|
||||
|
||||
it('should add TRANSITION_USER role', async () => {
|
||||
const useCase = createUseCase()
|
||||
|
||||
const result = await useCase.execute({
|
||||
userUuid: '00000000-0000-0000-0000-000000000000',
|
||||
status: 'VERIFIED',
|
||||
transitionType: 'items',
|
||||
transitionTimestamp: 123,
|
||||
})
|
||||
|
||||
expect(result.isFailed()).toBeFalsy()
|
||||
expect(roleService.removeRoleFromUser).toHaveBeenCalledWith(
|
||||
Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
|
||||
RoleName.create(RoleName.NAMES.TransitionUser).getValue(),
|
||||
)
|
||||
})
|
||||
|
||||
it('should update transition status', async () => {
|
||||
const useCase = createUseCase()
|
||||
|
||||
const result = await useCase.execute({
|
||||
userUuid: '00000000-0000-0000-0000-000000000000',
|
||||
status: TransitionStatus.STATUSES.InProgress,
|
||||
transitionType: 'items',
|
||||
transitionTimestamp: 123,
|
||||
})
|
||||
|
||||
expect(result.isFailed()).toBeFalsy()
|
||||
expect(transitionStatusRepository.updateStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should return error when user uuid is invalid', async () => {
|
||||
const useCase = createUseCase()
|
||||
|
||||
const result = await useCase.execute({
|
||||
userUuid: 'invalid',
|
||||
status: 'STARTED',
|
||||
transitionType: 'items',
|
||||
transitionTimestamp: 123,
|
||||
})
|
||||
|
||||
expect(result.isFailed()).toBeTruthy()
|
||||
expect(result.getError()).toEqual('Given value is not a valid uuid: invalid')
|
||||
})
|
||||
|
||||
it('should not update status if transition is already verified', async () => {
|
||||
transitionStatusRepository.getStatus = jest
|
||||
.fn()
|
||||
.mockResolvedValue(TransitionStatus.create(TransitionStatus.STATUSES.Verified).getValue())
|
||||
|
||||
const useCase = createUseCase()
|
||||
|
||||
const result = await useCase.execute({
|
||||
userUuid: '00000000-0000-0000-0000-000000000000',
|
||||
status: TransitionStatus.STATUSES.InProgress,
|
||||
transitionType: 'items',
|
||||
transitionTimestamp: 123,
|
||||
})
|
||||
|
||||
expect(result.isFailed()).toBeFalsy()
|
||||
expect(transitionStatusRepository.updateStatus).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should not update status if transition is already failed', async () => {
|
||||
transitionStatusRepository.getStatus = jest
|
||||
.fn()
|
||||
.mockResolvedValue(TransitionStatus.create(TransitionStatus.STATUSES.Failed).getValue())
|
||||
|
||||
const useCase = createUseCase()
|
||||
|
||||
const result = await useCase.execute({
|
||||
userUuid: '00000000-0000-0000-0000-000000000000',
|
||||
status: TransitionStatus.STATUSES.InProgress,
|
||||
transitionType: 'items',
|
||||
transitionTimestamp: 123,
|
||||
})
|
||||
|
||||
expect(result.isFailed()).toBeFalsy()
|
||||
expect(transitionStatusRepository.updateStatus).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
@@ -1,40 +0,0 @@
|
||||
import { Result, RoleName, TransitionStatus, UseCaseInterface, Uuid } from '@standardnotes/domain-core'
|
||||
import { TransitionStatusRepositoryInterface } from '../../Transition/TransitionStatusRepositoryInterface'
|
||||
import { UpdateTransitionStatusDTO } from './UpdateTransitionStatusDTO'
|
||||
import { RoleServiceInterface } from '../../Role/RoleServiceInterface'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
export class UpdateTransitionStatus implements UseCaseInterface<void> {
|
||||
constructor(
|
||||
private transitionStatusRepository: TransitionStatusRepositoryInterface,
|
||||
private roleService: RoleServiceInterface,
|
||||
private logger: Logger,
|
||||
) {}
|
||||
|
||||
async execute(dto: UpdateTransitionStatusDTO): Promise<Result<void>> {
|
||||
const userUuidOrError = Uuid.create(dto.userUuid)
|
||||
if (userUuidOrError.isFailed()) {
|
||||
return Result.fail(userUuidOrError.getError())
|
||||
}
|
||||
const userUuid = userUuidOrError.getValue()
|
||||
|
||||
const currentStatus = await this.transitionStatusRepository.getStatus(dto.userUuid, dto.transitionType)
|
||||
if (
|
||||
[TransitionStatus.STATUSES.Verified, TransitionStatus.STATUSES.Failed].includes(currentStatus?.value as string)
|
||||
) {
|
||||
this.logger.info(`User ${dto.userUuid} transition already finished.`)
|
||||
|
||||
return Result.ok()
|
||||
}
|
||||
|
||||
const transitionStatus = TransitionStatus.create(dto.status).getValue()
|
||||
|
||||
await this.transitionStatusRepository.updateStatus(dto.userUuid, dto.transitionType, transitionStatus)
|
||||
|
||||
if (dto.transitionType === 'items' && transitionStatus.value === TransitionStatus.STATUSES.Verified) {
|
||||
await this.roleService.removeRoleFromUser(userUuid, RoleName.create(RoleName.NAMES.TransitionUser).getValue())
|
||||
}
|
||||
|
||||
return Result.ok()
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
export interface UpdateTransitionStatusDTO {
|
||||
userUuid: string
|
||||
transitionType: 'items' | 'revisions'
|
||||
transitionTimestamp: number
|
||||
status: string
|
||||
}
|
||||
@@ -8,7 +8,8 @@ export interface UserRepositoryInterface {
|
||||
streamTeam(memberEmail?: Email): Promise<ReadStream>
|
||||
findOneByUuid(uuid: Uuid): Promise<User | null>
|
||||
findOneByUsernameOrEmail(usernameOrEmail: Email | Username): Promise<User | null>
|
||||
findAllCreatedBetween(start: Date, end: Date): Promise<User[]>
|
||||
findAllCreatedBetween(dto: { start: Date; end: Date; offset: number; limit: number }): Promise<User[]>
|
||||
countAllCreatedBetween(start: Date, end: Date): Promise<number>
|
||||
save(user: User): Promise<User>
|
||||
remove(user: User): Promise<User>
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import { TransitionStatus } from '@standardnotes/domain-core'
|
||||
import { TransitionStatusRepositoryInterface } from '../../Domain/Transition/TransitionStatusRepositoryInterface'
|
||||
|
||||
export class InMemoryTransitionStatusRepository implements TransitionStatusRepositoryInterface {
|
||||
private itemStatuses: Map<string, string> = new Map()
|
||||
private revisionStatuses: Map<string, string> = new Map()
|
||||
|
||||
async updateStatus(userUuid: string, transitionType: 'items' | 'revisions', status: TransitionStatus): Promise<void> {
|
||||
if (transitionType === 'items') {
|
||||
this.itemStatuses.set(userUuid, status.value)
|
||||
} else {
|
||||
this.revisionStatuses.set(userUuid, status.value)
|
||||
}
|
||||
}
|
||||
|
||||
async remove(userUuid: string, transitionType: 'items' | 'revisions'): Promise<void> {
|
||||
if (transitionType === 'items') {
|
||||
this.itemStatuses.delete(userUuid)
|
||||
} else {
|
||||
this.revisionStatuses.delete(userUuid)
|
||||
}
|
||||
}
|
||||
|
||||
async getStatus(userUuid: string, transitionType: 'items' | 'revisions'): Promise<TransitionStatus | null> {
|
||||
let status: string | null
|
||||
|
||||
if (transitionType === 'items') {
|
||||
status = this.itemStatuses.get(userUuid) ?? null
|
||||
} else {
|
||||
status = this.revisionStatuses.get(userUuid) ?? null
|
||||
}
|
||||
|
||||
if (status === null) {
|
||||
return null
|
||||
}
|
||||
|
||||
return TransitionStatus.create(status).getValue()
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user