mirror of
https://github.com/standardnotes/server
synced 2026-01-22 11:01:08 -05:00
Compare commits
10 Commits
@standardn
...
@standardn
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9b8d0ceb7 | ||
|
|
a2c1ebe675 | ||
|
|
3ef8e9ea24 | ||
|
|
c99334889c | ||
|
|
7ce9aba517 | ||
|
|
46257a058b | ||
|
|
979dc35cfc | ||
|
|
c99a447a04 | ||
|
|
6dd9fd5abd | ||
|
|
0d37cb293c |
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
|
||||
|
||||
11
.github/workflows/e2e-home-server.yml
vendored
11
.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:
|
||||
@@ -52,7 +43,7 @@ jobs:
|
||||
MYSQL_PASSWORD: standardnotes
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
|
||||
11
.github/workflows/e2e-self-hosted.yml
vendored
11
.github/workflows/e2e-self-hosted.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:
|
||||
@@ -35,7 +26,7 @@ jobs:
|
||||
- 9001:9001
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
|
||||
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
|
||||
|
||||
22
.github/workflows/pr.yml
vendored
22
.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
|
||||
@@ -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,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.
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 \
|
||||
|
||||
@@ -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,14 @@
|
||||
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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/analytics",
|
||||
"version": "2.32.0",
|
||||
"version": "2.32.2",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,16 @@
|
||||
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,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/api-gateway",
|
||||
"version": "1.79.13",
|
||||
"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,22 @@
|
||||
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
|
||||
|
||||
@@ -1,158 +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({ serviceName: 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 itemTransitionsTriggered = 0
|
||||
let revisionTransitionsTriggered = 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
|
||||
}
|
||||
|
||||
logger.info(
|
||||
`[TRANSITION ${timestamp}] Transition status for user ${user.uuid} - items status: ${itemsTransitionStatus?.value}, revisions status: ${revisionsTransitionStatus?.value}, has transition role: ${userHasTransitionRole}`,
|
||||
)
|
||||
|
||||
if (
|
||||
itemsTransitionStatus === null ||
|
||||
itemsTransitionStatus.value === TransitionStatus.STATUSES.Failed ||
|
||||
(itemsTransitionStatus.value === TransitionStatus.STATUSES.InProgress && forceRun)
|
||||
) {
|
||||
await transitionStatusRepository.remove(user.uuid, 'items')
|
||||
|
||||
await domainEventPublisher.publish(
|
||||
domainEventFactory.createTransitionRequestedEvent({
|
||||
userUuid: user.uuid,
|
||||
type: 'items',
|
||||
timestamp,
|
||||
}),
|
||||
)
|
||||
|
||||
itemTransitionsTriggered++
|
||||
}
|
||||
|
||||
if (
|
||||
revisionsTransitionStatus === null ||
|
||||
revisionsTransitionStatus.value === TransitionStatus.STATUSES.Failed ||
|
||||
(revisionsTransitionStatus.value === TransitionStatus.STATUSES.InProgress && forceRun)
|
||||
) {
|
||||
await transitionStatusRepository.remove(user.uuid, 'revisions')
|
||||
|
||||
await domainEventPublisher.publish(
|
||||
domainEventFactory.createTransitionRequestedEvent({
|
||||
userUuid: user.uuid,
|
||||
type: 'revisions',
|
||||
timestamp,
|
||||
}),
|
||||
)
|
||||
|
||||
revisionTransitionsTriggered++
|
||||
}
|
||||
}
|
||||
|
||||
logger.info(
|
||||
`[TRANSITION ${timestamp}] Triggered ${itemTransitionsTriggered} item transitions and ${revisionTransitionsTriggered} revision transitions for 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)
|
||||
})
|
||||
})
|
||||
@@ -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.159.0",
|
||||
"version": "1.160.0",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -258,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'
|
||||
@@ -645,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)
|
||||
@@ -660,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
|
||||
@@ -985,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(
|
||||
@@ -1174,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(
|
||||
@@ -1239,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)],
|
||||
[
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import * as IORedis from 'ioredis'
|
||||
|
||||
import { TransitionStatusRepositoryInterface } from '../../Domain/Transition/TransitionStatusRepositoryInterface'
|
||||
import { TransitionStatus } from '@standardnotes/domain-core'
|
||||
|
||||
export class RedisTransitionStatusRepository implements TransitionStatusRepositoryInterface {
|
||||
private readonly PREFIX = 'transition-back'
|
||||
|
||||
constructor(private redisClient: IORedis.Redis) {}
|
||||
|
||||
async remove(userUuid: string, transitionType: 'items' | 'revisions'): Promise<void> {
|
||||
await this.redisClient.del(`${this.PREFIX}:${transitionType}:${userUuid}`)
|
||||
}
|
||||
|
||||
async updateStatus(userUuid: string, transitionType: 'items' | 'revisions', status: TransitionStatus): Promise<void> {
|
||||
switch (status.value) {
|
||||
case TransitionStatus.STATUSES.Failed:
|
||||
case TransitionStatus.STATUSES.Verified:
|
||||
await this.redisClient.set(`${this.PREFIX}:${transitionType}:${userUuid}`, status.value)
|
||||
break
|
||||
case TransitionStatus.STATUSES.InProgress: {
|
||||
const ttl24Hours = 86_400
|
||||
await this.redisClient.setex(`${this.PREFIX}:${transitionType}:${userUuid}`, ttl24Hours, status.value)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async getStatus(userUuid: string, transitionType: 'items' | 'revisions'): Promise<TransitionStatus | null> {
|
||||
const status = await this.redisClient.get(`${this.PREFIX}:${transitionType}:${userUuid}`)
|
||||
|
||||
if (status === null) {
|
||||
return null
|
||||
}
|
||||
|
||||
const transitionStatusOrError = TransitionStatus.create(status)
|
||||
if (transitionStatusOrError.isFailed()) {
|
||||
return null
|
||||
}
|
||||
|
||||
return transitionStatusOrError.getValue()
|
||||
}
|
||||
}
|
||||
@@ -14,11 +14,21 @@ export class TypeORMUserRepository implements UserRepositoryInterface {
|
||||
private ormRepository: Repository<User>,
|
||||
) {}
|
||||
|
||||
async findAllCreatedBetween(start: Date, end: Date): Promise<User[]> {
|
||||
async findAllCreatedBetween(dto: { start: Date; end: Date; offset: number; limit: number }): Promise<User[]> {
|
||||
return this.ormRepository
|
||||
.createQueryBuilder('user')
|
||||
.where('user.created_at BETWEEN :start AND :end', { start: dto.start, end: dto.end })
|
||||
.orderBy('user.created_at', 'ASC')
|
||||
.take(dto.limit)
|
||||
.skip(dto.offset)
|
||||
.getMany()
|
||||
}
|
||||
|
||||
async countAllCreatedBetween(start: Date, end: Date): Promise<number> {
|
||||
return this.ormRepository
|
||||
.createQueryBuilder('user')
|
||||
.where('user.created_at BETWEEN :start AND :end', { start, end })
|
||||
.getMany()
|
||||
.getCount()
|
||||
}
|
||||
|
||||
async save(user: User): Promise<User> {
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.38.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.37.0...@standardnotes/domain-core@1.38.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.37.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.36.0...@standardnotes/domain-core@1.37.0) (2023-10-11)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/domain-core",
|
||||
"version": "1.37.0",
|
||||
"version": "1.38.0",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -21,36 +21,25 @@ describe('RoleName', () => {
|
||||
const plusUserRole = RoleName.create(RoleName.NAMES.PlusUser).getValue()
|
||||
const coreUser = RoleName.create(RoleName.NAMES.CoreUser).getValue()
|
||||
const internalTeamUser = RoleName.create(RoleName.NAMES.InternalTeamUser).getValue()
|
||||
const transitionUser = RoleName.create(RoleName.NAMES.TransitionUser).getValue()
|
||||
|
||||
expect(internalTeamUser.hasMoreOrEqualPowerTo(proUserRole)).toBeTruthy()
|
||||
expect(internalTeamUser.hasMoreOrEqualPowerTo(proUserRole)).toBeTruthy()
|
||||
expect(internalTeamUser.hasMoreOrEqualPowerTo(plusUserRole)).toBeTruthy()
|
||||
expect(internalTeamUser.hasMoreOrEqualPowerTo(coreUser)).toBeTruthy()
|
||||
expect(internalTeamUser.hasMoreOrEqualPowerTo(transitionUser)).toBeTruthy()
|
||||
|
||||
expect(proUserRole.hasMoreOrEqualPowerTo(internalTeamUser)).toBeFalsy()
|
||||
expect(proUserRole.hasMoreOrEqualPowerTo(proUserRole)).toBeTruthy()
|
||||
expect(proUserRole.hasMoreOrEqualPowerTo(plusUserRole)).toBeTruthy()
|
||||
expect(proUserRole.hasMoreOrEqualPowerTo(coreUser)).toBeTruthy()
|
||||
expect(proUserRole.hasMoreOrEqualPowerTo(transitionUser)).toBeTruthy()
|
||||
|
||||
expect(plusUserRole.hasMoreOrEqualPowerTo(internalTeamUser)).toBeFalsy()
|
||||
expect(plusUserRole.hasMoreOrEqualPowerTo(proUserRole)).toBeFalsy()
|
||||
expect(plusUserRole.hasMoreOrEqualPowerTo(plusUserRole)).toBeTruthy()
|
||||
expect(plusUserRole.hasMoreOrEqualPowerTo(coreUser)).toBeTruthy()
|
||||
expect(plusUserRole.hasMoreOrEqualPowerTo(transitionUser)).toBeTruthy()
|
||||
|
||||
expect(coreUser.hasMoreOrEqualPowerTo(internalTeamUser)).toBeFalsy()
|
||||
expect(coreUser.hasMoreOrEqualPowerTo(proUserRole)).toBeFalsy()
|
||||
expect(coreUser.hasMoreOrEqualPowerTo(plusUserRole)).toBeFalsy()
|
||||
expect(coreUser.hasMoreOrEqualPowerTo(coreUser)).toBeTruthy()
|
||||
expect(coreUser.hasMoreOrEqualPowerTo(transitionUser)).toBeTruthy()
|
||||
|
||||
expect(transitionUser.hasMoreOrEqualPowerTo(internalTeamUser)).toBeFalsy()
|
||||
expect(transitionUser.hasMoreOrEqualPowerTo(proUserRole)).toBeFalsy()
|
||||
expect(transitionUser.hasMoreOrEqualPowerTo(plusUserRole)).toBeFalsy()
|
||||
expect(transitionUser.hasMoreOrEqualPowerTo(coreUser)).toBeTruthy()
|
||||
expect(transitionUser.hasMoreOrEqualPowerTo(transitionUser)).toBeTruthy()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -8,7 +8,6 @@ export class RoleName extends ValueObject<RoleNameProps> {
|
||||
PlusUser: 'PLUS_USER',
|
||||
ProUser: 'PRO_USER',
|
||||
InternalTeamUser: 'INTERNAL_TEAM_USER',
|
||||
TransitionUser: 'TRANSITION_USER',
|
||||
VaultsUser: 'VAULTS_USER',
|
||||
}
|
||||
|
||||
@@ -21,20 +20,12 @@ export class RoleName extends ValueObject<RoleNameProps> {
|
||||
case RoleName.NAMES.InternalTeamUser:
|
||||
return true
|
||||
case RoleName.NAMES.ProUser:
|
||||
return [
|
||||
RoleName.NAMES.CoreUser,
|
||||
RoleName.NAMES.PlusUser,
|
||||
RoleName.NAMES.ProUser,
|
||||
RoleName.NAMES.TransitionUser,
|
||||
].includes(roleName.value)
|
||||
return [RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser].includes(roleName.value)
|
||||
case RoleName.NAMES.PlusUser:
|
||||
return [RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser, RoleName.NAMES.TransitionUser].includes(
|
||||
roleName.value,
|
||||
)
|
||||
return [RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser].includes(roleName.value)
|
||||
case RoleName.NAMES.CoreUser:
|
||||
case RoleName.NAMES.TransitionUser:
|
||||
case RoleName.NAMES.VaultsUser:
|
||||
return [RoleName.NAMES.CoreUser, RoleName.NAMES.TransitionUser].includes(roleName.value)
|
||||
return [RoleName.NAMES.CoreUser].includes(roleName.value)
|
||||
/*istanbul ignore next*/
|
||||
default:
|
||||
throw new Error(`Invalid role name: ${this.value}`)
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
import { Result } from '../Core/Result'
|
||||
import { ValueObject } from '../Core/ValueObject'
|
||||
import { TransitionStatusProps } from './TransitionStatusProps'
|
||||
|
||||
export class TransitionStatus extends ValueObject<TransitionStatusProps> {
|
||||
static readonly STATUSES = {
|
||||
InProgress: 'IN_PROGRESS',
|
||||
Failed: 'FAILED',
|
||||
Verified: 'VERIFIED',
|
||||
}
|
||||
|
||||
get value(): string {
|
||||
return this.props.value
|
||||
}
|
||||
|
||||
private constructor(props: TransitionStatusProps) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
static create(name: string): Result<TransitionStatus> {
|
||||
const isValidName = Object.values(this.STATUSES).includes(name)
|
||||
if (!isValidName) {
|
||||
return Result.fail<TransitionStatus>('Invalid transition status name.')
|
||||
} else {
|
||||
return Result.ok<TransitionStatus>(new TransitionStatus({ value: name }))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
export interface TransitionStatusProps {
|
||||
value: string
|
||||
}
|
||||
@@ -69,8 +69,5 @@ export * from './SharedVault/SharedVaultUserProps'
|
||||
export * from './Subscription/SubscriptionPlanName'
|
||||
export * from './Subscription/SubscriptionPlanNameProps'
|
||||
|
||||
export * from './Transition/TransitionStatus'
|
||||
export * from './Transition/TransitionStatusProps'
|
||||
|
||||
export * from './UseCase/SyncUseCaseInterface'
|
||||
export * from './UseCase/UseCaseInterface'
|
||||
|
||||
@@ -3,6 +3,16 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.20.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.20.1...@standardnotes/domain-events-infra@1.20.2) (2023-10-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||
|
||||
## [1.20.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.20.0...@standardnotes/domain-events-infra@1.20.1) (2023-10-18)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* remove ip attributes in opentelemetry http instrumentation ([#874](https://github.com/standardnotes/server/issues/874)) ([7ce9aba](https://github.com/standardnotes/server/commit/7ce9aba517435034f491c9f080f671285fb91b91))
|
||||
|
||||
# [1.20.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.19.7...@standardnotes/domain-events-infra@1.20.0) (2023-10-17)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/domain-events-infra",
|
||||
"version": "1.20.0",
|
||||
"version": "1.20.2",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
@@ -27,18 +27,18 @@
|
||||
"@aws-sdk/client-sns": "^3.427.0",
|
||||
"@aws-sdk/client-sqs": "^3.427.0",
|
||||
"@opentelemetry/api": "^1.6.0",
|
||||
"@opentelemetry/exporter-metrics-otlp-proto": "^0.43.0",
|
||||
"@opentelemetry/exporter-trace-otlp-grpc": "^0.43.0",
|
||||
"@opentelemetry/exporter-metrics-otlp-proto": "^0.44.0",
|
||||
"@opentelemetry/exporter-trace-otlp-grpc": "^0.44.0",
|
||||
"@opentelemetry/id-generator-aws-xray": "^1.2.1",
|
||||
"@opentelemetry/instrumentation-aws-sdk": "^0.36.0",
|
||||
"@opentelemetry/instrumentation-express": "^0.33.1",
|
||||
"@opentelemetry/instrumentation-http": "^0.43.0",
|
||||
"@opentelemetry/instrumentation-ioredis": "^0.35.1",
|
||||
"@opentelemetry/instrumentation-winston": "^0.32.1",
|
||||
"@opentelemetry/instrumentation-aws-sdk": "^0.36.1",
|
||||
"@opentelemetry/instrumentation-express": "^0.33.2",
|
||||
"@opentelemetry/instrumentation-http": "^0.44.0",
|
||||
"@opentelemetry/instrumentation-ioredis": "^0.35.2",
|
||||
"@opentelemetry/instrumentation-winston": "^0.32.2",
|
||||
"@opentelemetry/propagator-aws-xray": "^1.3.1",
|
||||
"@opentelemetry/resource-detector-aws": "^1.3.1",
|
||||
"@opentelemetry/sdk-node": "^0.43.0",
|
||||
"@opentelemetry/semantic-conventions": "^1.17.0",
|
||||
"@opentelemetry/resource-detector-aws": "^1.3.2",
|
||||
"@opentelemetry/sdk-node": "^0.44.0",
|
||||
"@opentelemetry/semantic-conventions": "^1.17.1",
|
||||
"@standardnotes/domain-events": "workspace:*",
|
||||
"ioredis": "^5.2.4",
|
||||
"opentelemetry-instrumentation-typeorm": "^0.39.1",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as OpenTelemetrySDKNode from '@opentelemetry/sdk-node'
|
||||
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'
|
||||
import { SemanticAttributes, SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'
|
||||
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc'
|
||||
import { AWSXRayIdGenerator } from '@opentelemetry/id-generator-aws-xray'
|
||||
import * as AwsResourceDetectors from '@opentelemetry/resource-detector-aws'
|
||||
@@ -10,9 +10,11 @@ import { AwsInstrumentation } from '@opentelemetry/instrumentation-aws-sdk'
|
||||
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-proto'
|
||||
import { WinstonInstrumentation } from '@opentelemetry/instrumentation-winston'
|
||||
import { IORedisInstrumentation } from '@opentelemetry/instrumentation-ioredis'
|
||||
import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express'
|
||||
import { IncomingMessage } from 'http'
|
||||
import { Attributes } from '@opentelemetry/api'
|
||||
|
||||
import { OpenTelemetrySDKInterface } from './OpenTelemetrySDKInterface'
|
||||
import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express'
|
||||
|
||||
export class OpenTelemetrySDK implements OpenTelemetrySDKInterface {
|
||||
private declare sdk: OpenTelemetrySDKNode.NodeSDK
|
||||
@@ -63,6 +65,11 @@ export class OpenTelemetrySDK implements OpenTelemetrySDKInterface {
|
||||
|
||||
return isHealthCheckUrl
|
||||
},
|
||||
startIncomingSpanHook: (_request: IncomingMessage): Attributes => {
|
||||
return {
|
||||
[SemanticAttributes.HTTP_CLIENT_IP]: undefined,
|
||||
}
|
||||
},
|
||||
}),
|
||||
new ExpressInstrumentation(),
|
||||
new AwsInstrumentation({
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [2.133.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.132.3...@standardnotes/domain-events@2.133.0) (2023-10-19)
|
||||
|
||||
### Features
|
||||
|
||||
* remove transition state ([#882](https://github.com/standardnotes/server/issues/882)) ([a2c1ebe](https://github.com/standardnotes/server/commit/a2c1ebe675cd5678c923715056a6966f465a15d6))
|
||||
|
||||
## [2.132.3](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.132.2...@standardnotes/domain-events@2.132.3) (2023-10-12)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/domain-events",
|
||||
"version": "2.132.3",
|
||||
"version": "2.133.0",
|
||||
"engines": {
|
||||
"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