Compare commits

...

12 Commits

Author SHA1 Message Date
standardci
832a48ac76 chore(release): publish new version
- @standardnotes/analytics@2.19.10
 - @standardnotes/api-gateway@1.46.5
 - @standardnotes/auth-server@1.84.0
 - @standardnotes/domain-events-infra@1.9.65
 - @standardnotes/domain-events@2.106.0
 - @standardnotes/event-store@1.6.64
 - @standardnotes/files-server@1.9.10
 - @standardnotes/revisions-server@1.10.18
 - @standardnotes/scheduler-server@1.16.14
 - @standardnotes/syncing-server@1.29.5
 - @standardnotes/websockets-server@1.5.10
 - @standardnotes/workspace-server@1.19.13
2023-01-19 22:31:28 +00:00
Mo
2db0c125fe feat: offline roles (#419) 2023-01-19 16:29:36 -06:00
standardci
20d9624bc6 chore(release): publish new version
- @standardnotes/auth-server@1.83.1
2023-01-19 19:40:49 +00:00
moughxyz
f20ee68f50 Revert "feat: include roles in offline features request (#418)"
This reverts commit 2e7fdd93dd.
2023-01-19 13:38:46 -06:00
standardci
cbf45ce3eb chore(release): publish new version
- @standardnotes/auth-server@1.83.0
2023-01-19 19:18:16 +00:00
Mo
2e7fdd93dd feat: include roles in offline features request (#418) 2023-01-19 13:16:16 -06:00
standardci
8ce38f82b5 chore(release): publish new version
- @standardnotes/analytics@2.19.9
 - @standardnotes/api-gateway@1.46.4
 - @standardnotes/auth-server@1.82.6
 - @standardnotes/domain-events-infra@1.9.64
 - @standardnotes/domain-events@2.105.5
 - @standardnotes/event-store@1.6.63
 - @standardnotes/files-server@1.9.9
 - @standardnotes/revisions-server@1.10.17
 - @standardnotes/scheduler-server@1.16.13
 - @standardnotes/syncing-server@1.29.4
 - @standardnotes/websockets-server@1.5.9
 - @standardnotes/workspace-server@1.19.12
2023-01-19 16:19:54 +00:00
Aman Harwara
ec5429eeec fix: expected value for unit test (#417) 2023-01-19 21:47:32 +05:30
standardci
4b17c4045d chore(release): publish new version
- @standardnotes/analytics@2.19.8
 - @standardnotes/api-gateway@1.46.3
 - @standardnotes/auth-server@1.82.5
 - @standardnotes/common@1.46.3
 - @standardnotes/domain-events-infra@1.9.63
 - @standardnotes/domain-events@2.105.4
 - @standardnotes/event-store@1.6.62
 - @standardnotes/files-server@1.9.8
 - @standardnotes/predicates@1.6.4
 - @standardnotes/revisions-server@1.10.16
 - @standardnotes/scheduler-server@1.16.12
 - @standardnotes/security@1.7.5
 - @standardnotes/syncing-server@1.29.3
 - @standardnotes/websockets-server@1.5.8
 - @standardnotes/workspace-server@1.19.11
2023-01-19 14:13:50 +00:00
Karol Sójko
aaf42e4693 refactor: remove Uuid from @standardnotes/common in favour of @standardnotes/domain-core definition 2023-01-19 15:11:47 +01:00
standardci
0e3cbfc40b chore(release): publish new version
- @standardnotes/analytics@2.19.7
 - @standardnotes/api-gateway@1.46.2
 - @standardnotes/auth-server@1.82.4
 - @standardnotes/common@1.46.2
 - @standardnotes/domain-events-infra@1.9.62
 - @standardnotes/domain-events@2.105.3
 - @standardnotes/event-store@1.6.61
 - @standardnotes/files-server@1.9.7
 - @standardnotes/predicates@1.6.3
 - @standardnotes/revisions-server@1.10.15
 - @standardnotes/scheduler-server@1.16.11
 - @standardnotes/security@1.7.4
 - @standardnotes/syncing-server@1.29.2
 - @standardnotes/websockets-server@1.5.7
 - @standardnotes/workspace-server@1.19.10
2023-01-19 13:08:22 +00:00
Karol Sójko
a95ca05c10 refactor: remove RoleName from @standardnotes/common in favour of @standardnotes/domain-core definition 2023-01-19 14:05:48 +01:00
190 changed files with 691 additions and 647 deletions

23
.pnp.cjs generated
View File

@@ -2693,7 +2693,7 @@ const RAW_RUNTIME_STATE =
["@standardnotes/api-gateway", "workspace:packages/api-gateway"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@sentry/node", "npm:7.28.1"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
["@standardnotes/security", "workspace:packages/security"],\
@@ -2758,7 +2758,7 @@ const RAW_RUNTIME_STATE =
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
["@standardnotes/features", "npm:1.58.0"],\
["@standardnotes/features", "npm:1.58.1"],\
["@standardnotes/predicates", "workspace:packages/predicates"],\
["@standardnotes/responses", "npm:1.11.1"],\
["@standardnotes/security", "workspace:packages/security"],\
@@ -2862,15 +2862,13 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/domain-events/",\
"packageDependencies": [\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/features", "npm:1.53.1"],\
["@standardnotes/features", "npm:1.58.1"],\
["@standardnotes/predicates", "workspace:packages/predicates"],\
["@standardnotes/security", "workspace:packages/security"],\
["@types/jest", "npm:29.1.1"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.30.5"],\
["eslint-plugin-prettier", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:4.2.1"],\
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
["reflect-metadata", "npm:0.1.13"],\
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.0.3"],\
["typescript", "patch:typescript@npm%3A4.8.4#optional!builtin<compat/typescript>::version=4.8.4&hash=701156"]\
],\
@@ -2970,12 +2968,13 @@ const RAW_RUNTIME_STATE =
],\
"linkType": "HARD"\
}],\
["npm:1.58.0", {\
"packageLocation": "./.yarn/cache/@standardnotes-features-npm-1.58.0-5a58b65873-028c13956a.zip/node_modules/@standardnotes/features/",\
["npm:1.58.1", {\
"packageLocation": "./.yarn/cache/@standardnotes-features-npm-1.58.1-a51ef65e8a-558e4506d8.zip/node_modules/@standardnotes/features/",\
"packageDependencies": [\
["@standardnotes/features", "npm:1.58.0"],\
["@standardnotes/features", "npm:1.58.1"],\
["@standardnotes/auth", "npm:3.19.4"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/security", "workspace:packages/security"],\
["reflect-metadata", "npm:0.1.13"]\
],\
@@ -2988,8 +2987,8 @@ const RAW_RUNTIME_STATE =
"packageDependencies": [\
["@standardnotes/files-server", "workspace:packages/files"],\
["@sentry/node", "npm:7.28.1"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/config", "npm:2.4.3"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
["@standardnotes/security", "workspace:packages/security"],\
@@ -3081,12 +3080,10 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/predicates/",\
"packageDependencies": [\
["@standardnotes/predicates", "workspace:packages/predicates"],\
["@standardnotes/common", "workspace:packages/common"],\
["@types/jest", "npm:29.1.1"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.30.5"],\
["eslint-plugin-prettier", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:4.2.1"],\
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
["reflect-metadata", "npm:0.1.13"],\
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.0.3"],\
["typescript", "patch:typescript@npm%3A4.8.4#optional!builtin<compat/typescript>::version=4.8.4&hash=701156"]\
],\
@@ -3169,7 +3166,6 @@ const RAW_RUNTIME_STATE =
["@standardnotes/scheduler-server", "workspace:packages/scheduler"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@sentry/node", "npm:7.28.1"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
@@ -3205,7 +3201,6 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/security/",\
"packageDependencies": [\
["@standardnotes/security", "workspace:packages/security"],\
["@standardnotes/common", "workspace:packages/common"],\
["@types/jest", "npm:29.1.1"],\
["@types/jsonwebtoken", "npm:9.0.1"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.30.5"],\
@@ -3398,7 +3393,7 @@ const RAW_RUNTIME_STATE =
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@sentry/node", "npm:7.28.1"],\
["@standardnotes/api", "npm:1.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
["@standardnotes/security", "workspace:packages/security"],\

View File

@@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.19.10](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.19.9...@standardnotes/analytics@2.19.10) (2023-01-19)
**Note:** Version bump only for package @standardnotes/analytics
## [2.19.9](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.19.8...@standardnotes/analytics@2.19.9) (2023-01-19)
**Note:** Version bump only for package @standardnotes/analytics
## [2.19.8](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.19.7...@standardnotes/analytics@2.19.8) (2023-01-19)
**Note:** Version bump only for package @standardnotes/analytics
## [2.19.7](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.19.6...@standardnotes/analytics@2.19.7) (2023-01-19)
**Note:** Version bump only for package @standardnotes/analytics
## [2.19.6](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.19.5...@standardnotes/analytics@2.19.6) (2023-01-18)
**Note:** Version bump only for package @standardnotes/analytics

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/analytics",
"version": "2.19.6",
"version": "2.19.10",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -1,9 +1,8 @@
import { Uuid } from '@standardnotes/common'
import { AnalyticsEntity } from './AnalyticsEntity'
export interface AnalyticsEntityRepositoryInterface {
save(analyticsEntity: AnalyticsEntity): Promise<AnalyticsEntity>
remove(analyticsEntity: AnalyticsEntity): Promise<void>
findOneByUserUuid(userUuid: Uuid): Promise<AnalyticsEntity | null>
findOneByUserUuid(userUuid: string): Promise<AnalyticsEntity | null>
findOneByUserEmail(email: string): Promise<AnalyticsEntity | null>
}

View File

@@ -1,8 +1,8 @@
import { Either, Uuid } from '@standardnotes/common'
import { Either } from '@standardnotes/common'
export type GetUserAnalyticsIdDTO = Either<
{
userUuid: Uuid
userUuid: string
},
{
userEmail: string

View File

@@ -1,4 +1,3 @@
import { Uuid } from '@standardnotes/common'
import { inject, injectable } from 'inversify'
import { Repository } from 'typeorm'
@@ -20,7 +19,7 @@ export class MySQLAnalyticsEntityRepository implements AnalyticsEntityRepository
.getOne()
}
async findOneByUserUuid(userUuid: Uuid): Promise<AnalyticsEntity | null> {
async findOneByUserUuid(userUuid: string): Promise<AnalyticsEntity | null> {
return this.ormRepository
.createQueryBuilder('analytics_entity')
.where('analytics_entity.user_uuid = :userUuid', { userUuid })

View File

@@ -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.46.5](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.46.4...@standardnotes/api-gateway@1.46.5) (2023-01-19)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.46.4](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.46.3...@standardnotes/api-gateway@1.46.4) (2023-01-19)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.46.3](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.46.2...@standardnotes/api-gateway@1.46.3) (2023-01-19)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.46.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.46.1...@standardnotes/api-gateway@1.46.2) (2023-01-19)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.46.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.46.0...@standardnotes/api-gateway@1.46.1) (2023-01-18)
**Note:** Version bump only for package @standardnotes/api-gateway

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api-gateway",
"version": "1.46.1",
"version": "1.46.5",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -22,7 +22,7 @@
"dependencies": {
"@newrelic/winston-enricher": "^4.0.0",
"@sentry/node": "^7.28.1",
"@standardnotes/common": "workspace:^",
"@standardnotes/domain-core": "workspace:^",
"@standardnotes/domain-events": "workspace:*",
"@standardnotes/domain-events-infra": "workspace:*",
"@standardnotes/security": "workspace:*",

View File

@@ -1,5 +1,5 @@
import { CrossServiceTokenData } from '@standardnotes/security'
import { RoleName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { TimerInterface } from '@standardnotes/time'
import { NextFunction, Request, Response } from 'express'
import { inject, injectable } from 'inversify'
@@ -76,7 +76,7 @@ export class AuthMiddleware extends BaseMiddleware {
response.locals.freeUser =
decodedToken.roles.length === 1 &&
decodedToken.roles.find((role) => role.name === RoleName.CoreUser) !== undefined
decodedToken.roles.find((role) => role.name === RoleName.NAMES.CoreUser) !== undefined
if (this.crossServiceTokenCacheTTL && !crossServiceTokenFetchedFromCache) {
await this.crossServiceTokenCache.set({

View File

@@ -1,5 +1,5 @@
import { CrossServiceTokenData } from '@standardnotes/security'
import { RoleName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { NextFunction, Request, Response } from 'express'
import { inject, injectable } from 'inversify'
import { BaseMiddleware } from 'inversify-express-utils'
@@ -62,7 +62,7 @@ export class WebSocketAuthMiddleware extends BaseMiddleware {
response.locals.freeUser =
decodedToken.roles.length === 1 &&
decodedToken.roles.find((role) => role.name === RoleName.CoreUser) !== undefined
decodedToken.roles.find((role) => role.name === RoleName.NAMES.CoreUser) !== undefined
response.locals.userUuid = decodedToken.user.uuid
response.locals.roles = decodedToken.roles
} catch (error) {

View File

@@ -3,6 +3,38 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.84.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.83.1...@standardnotes/auth-server@1.84.0) (2023-01-19)
### Features
* offline roles ([#419](https://github.com/standardnotes/server/issues/419)) ([2db0c12](https://github.com/standardnotes/server/commit/2db0c125fe5872c5898103c2388881ab416b5a99))
## [1.83.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.83.0...@standardnotes/auth-server@1.83.1) (2023-01-19)
### Reverts
* Revert "feat: include roles in offline features request (#418)" ([f20ee68](https://github.com/standardnotes/server/commit/f20ee68f504449b6ff37748c4d7f83c08bb4039d)), closes [#418](https://github.com/standardnotes/server/issues/418)
# [1.83.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.82.6...@standardnotes/auth-server@1.83.0) (2023-01-19)
### Features
* include roles in offline features request ([#418](https://github.com/standardnotes/server/issues/418)) ([2e7fdd9](https://github.com/standardnotes/server/commit/2e7fdd93dd3b07e0a9f2e72521251af1d15660d4))
## [1.82.6](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.82.5...@standardnotes/auth-server@1.82.6) (2023-01-19)
### Bug Fixes
* expected value for unit test ([#417](https://github.com/standardnotes/server/issues/417)) ([ec5429e](https://github.com/standardnotes/server/commit/ec5429eeec8ea6422ed6e0e798e0f16aa9f78c95))
## [1.82.5](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.82.4...@standardnotes/auth-server@1.82.5) (2023-01-19)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.82.4](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.82.3...@standardnotes/auth-server@1.82.4) (2023-01-19)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.82.3](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.82.2...@standardnotes/auth-server@1.82.3) (2023-01-18)
**Note:** Version bump only for package @standardnotes/auth-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/auth-server",
"version": "1.82.3",
"version": "1.84.0",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -42,7 +42,7 @@
"@standardnotes/domain-core": "workspace:^",
"@standardnotes/domain-events": "workspace:*",
"@standardnotes/domain-events-infra": "workspace:*",
"@standardnotes/features": "^1.58.0",
"@standardnotes/features": "^1.58.1",
"@standardnotes/predicates": "workspace:*",
"@standardnotes/responses": "^1.6.39",
"@standardnotes/security": "workspace:*",

View File

@@ -121,14 +121,7 @@ import { RedisOfflineSubscriptionTokenRepository } from '../Infra/Redis/RedisOff
import { CreateOfflineSubscriptionToken } from '../Domain/UseCase/CreateOfflineSubscriptionToken/CreateOfflineSubscriptionToken'
import { AuthenticateOfflineSubscriptionToken } from '../Domain/UseCase/AuthenticateOfflineSubscriptionToken/AuthenticateOfflineSubscriptionToken'
import { SubscriptionCancelledEventHandler } from '../Domain/Handler/SubscriptionCancelledEventHandler'
import {
ContentDecoder,
ContentDecoderInterface,
ProtocolVersion,
Uuid,
UuidValidator,
ValidatorInterface,
} from '@standardnotes/common'
import { ContentDecoder, ContentDecoderInterface, ProtocolVersion } from '@standardnotes/common'
import { GetUserOfflineSubscription } from '../Domain/UseCase/GetUserOfflineSubscription/GetUserOfflineSubscription'
import { ApiGatewayOfflineAuthMiddleware } from '../Controller/ApiGatewayOfflineAuthMiddleware'
import { UserEmailChangedEventHandler } from '../Domain/Handler/UserEmailChangedEventHandler'
@@ -532,7 +525,6 @@ export class ContainerConfigLoader {
.bind<SelectorInterface<boolean>>(TYPES.BooleanSelector)
.toConstantValue(new DeterministicSelector<boolean>())
container.bind<UserSubscriptionServiceInterface>(TYPES.UserSubscriptionService).to(UserSubscriptionService)
container.bind<ValidatorInterface<Uuid>>(TYPES.UuidValidator).toConstantValue(new UuidValidator())
if (env.get('SNS_TOPIC_ARN', true)) {
container

View File

@@ -207,7 +207,6 @@ const TYPES = {
ProtocolVersionSelector: Symbol.for('ProtocolVersionSelector'),
BooleanSelector: Symbol.for('BooleanSelector'),
UserSubscriptionService: Symbol.for('UserSubscriptionService'),
UuidValidator: Symbol.for('UuidValidator'),
}
export default TYPES

View File

@@ -4,7 +4,7 @@ import { ApiGatewayAuthMiddleware } from './ApiGatewayAuthMiddleware'
import { NextFunction, Request, Response } from 'express'
import { Logger } from 'winston'
import { CrossServiceTokenData, TokenDecoderInterface } from '@standardnotes/security'
import { RoleName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
describe('ApiGatewayAuthMiddleware', () => {
let tokenDecoder: TokenDecoderInterface<CrossServiceTokenData>
@@ -28,7 +28,7 @@ describe('ApiGatewayAuthMiddleware', () => {
roles: [
{
uuid: 'a-b-c',
name: RoleName.CoreUser,
name: RoleName.NAMES.CoreUser,
},
],
})
@@ -56,7 +56,7 @@ describe('ApiGatewayAuthMiddleware', () => {
expect(response.locals.roles).toEqual([
{
uuid: 'a-b-c',
name: RoleName.CoreUser,
name: RoleName.NAMES.CoreUser,
},
])

View File

@@ -12,7 +12,6 @@ import {
SubscriptionInviteResponse,
SubscriptionServerInterface,
} from '@standardnotes/api'
import { RoleName } from '@standardnotes/common'
import { inject, injectable } from 'inversify'
import TYPES from '../Bootstrap/Types'
@@ -88,7 +87,7 @@ export class SubscriptionInvitesController implements SubscriptionServerInterfac
inviterEmail: params.inviterEmail as string,
inviterUuid: params.inviterUuid as string,
inviteeIdentifier: params.identifier,
inviterRoles: params.inviterRoles as RoleName[],
inviterRoles: params.inviterRoles as string[],
})
if (result.success) {

View File

@@ -1,5 +1,5 @@
import { CrossServiceTokenData, TokenEncoderInterface } from '@standardnotes/security'
import { ErrorTag, RoleName } from '@standardnotes/common'
import { ErrorTag } from '@standardnotes/common'
import { SettingName } from '@standardnotes/settings'
import { Request, Response } from 'express'
import { inject } from 'inversify'
@@ -101,10 +101,10 @@ export class SubscriptionTokensController extends BaseHttpController {
return <{ uuid: string; email: string }>await this.userProjector.projectSimple(user)
}
private async projectRoles(roles: Array<Role>): Promise<Array<{ uuid: string; name: RoleName }>> {
private async projectRoles(roles: Array<Role>): Promise<Array<{ uuid: string; name: string }>> {
const roleProjections = []
for (const role of roles) {
roleProjections.push(<{ uuid: string; name: RoleName }>await this.roleProjector.projectSimple(role))
roleProjections.push(<{ uuid: string; name: string }>await this.roleProjector.projectSimple(role))
}
return roleProjections

View File

@@ -4,27 +4,22 @@ import { Request, Response } from 'express'
import { results } from 'inversify-express-utils'
import { ValetTokenController } from './ValetTokenController'
import { CreateValetToken } from '../Domain/UseCase/CreateValetToken/CreateValetToken'
import { Uuid, ValidatorInterface } from '@standardnotes/common'
describe('ValetTokenController', () => {
let createValetToken: CreateValetToken
let uuidValidator: ValidatorInterface<Uuid>
let request: Request
let response: Response
const createController = () => new ValetTokenController(createValetToken, uuidValidator)
const createController = () => new ValetTokenController(createValetToken)
beforeEach(() => {
createValetToken = {} as jest.Mocked<CreateValetToken>
createValetToken.execute = jest.fn().mockReturnValue({ success: true, valetToken: 'foobar' })
uuidValidator = {} as jest.Mocked<ValidatorInterface<Uuid>>
uuidValidator.validate = jest.fn().mockReturnValue(true)
request = {
body: {
operation: 'write',
resources: ['1-2-3/2-3-4'],
resources: [{ remoteIdentifier: '00000000-0000-0000-0000-000000000000' }],
},
} as jest.Mocked<Request>
@@ -42,13 +37,13 @@ describe('ValetTokenController', () => {
expect(createValetToken.execute).toHaveBeenCalledWith({
operation: 'write',
userUuid: '1-2-3',
resources: ['1-2-3/2-3-4'],
resources: [{ remoteIdentifier: '00000000-0000-0000-0000-000000000000' }],
})
expect(await result.content.readAsStringAsync()).toEqual('{"success":true,"valetToken":"foobar"}')
})
it('should not create a valet token if the remote resource identifier is not a valid uuid', async () => {
uuidValidator.validate = jest.fn().mockReturnValue(false)
request.body.resources = ['00000000-0000-0000-0000-000000000000', 'invalid-uuid']
const httpResponse = <results.JsonResult>await createController().create(request, response)
const result = await httpResponse.executeAsync()
@@ -68,7 +63,7 @@ describe('ValetTokenController', () => {
expect(createValetToken.execute).toHaveBeenCalledWith({
operation: 'read',
userUuid: '1-2-3',
resources: ['1-2-3/2-3-4'],
resources: [{ remoteIdentifier: '00000000-0000-0000-0000-000000000000' }],
})
expect(await result.content.readAsStringAsync()).toEqual('{"success":true,"valetToken":"foobar"}')
})
@@ -106,7 +101,7 @@ describe('ValetTokenController', () => {
expect(createValetToken.execute).toHaveBeenCalledWith({
operation: 'write',
userUuid: '1-2-3',
resources: ['1-2-3/2-3-4'],
resources: [{ remoteIdentifier: '00000000-0000-0000-0000-000000000000' }],
})
expect(await result.content.readAsStringAsync()).toEqual('{"success":false}')

View File

@@ -11,15 +11,13 @@ import { CreateValetTokenPayload } from '@standardnotes/responses'
import TYPES from '../Bootstrap/Types'
import { CreateValetToken } from '../Domain/UseCase/CreateValetToken/CreateValetToken'
import { ErrorTag, Uuid, ValidatorInterface } from '@standardnotes/common'
import { ErrorTag } from '@standardnotes/common'
import { ValetTokenOperation } from '@standardnotes/security'
import { Uuid } from '@standardnotes/domain-core'
@controller('/valet-tokens', TYPES.ApiGatewayAuthMiddleware)
export class ValetTokenController extends BaseHttpController {
constructor(
@inject(TYPES.CreateValetToken) private createValetKey: CreateValetToken,
@inject(TYPES.UuidValidator) private uuidValitor: ValidatorInterface<Uuid>,
) {
constructor(@inject(TYPES.CreateValetToken) private createValetKey: CreateValetToken) {
super()
}
@@ -40,7 +38,8 @@ export class ValetTokenController extends BaseHttpController {
}
for (const resource of payload.resources) {
if (!this.uuidValitor.validate(resource.remoteIdentifier)) {
const resourceUuidOrError = Uuid.create(resource.remoteIdentifier)
if (resourceUuidOrError.isFailed()) {
return this.json(
{
error: {

View File

@@ -1,8 +1,8 @@
import { ProtocolVersion, Uuid } from '@standardnotes/common'
import { ProtocolVersion } from '@standardnotes/common'
export interface AuthResponse {
user: {
uuid: Uuid
uuid: string
email: string
protocolVersion: ProtocolVersion
}

View File

@@ -1,5 +1,5 @@
import { SessionTokenData, TokenEncoderInterface } from '@standardnotes/security'
import { ProtocolVersion, Uuid } from '@standardnotes/common'
import { ProtocolVersion } from '@standardnotes/common'
import * as crypto from 'crypto'
import { inject, injectable } from 'inversify'
@@ -40,7 +40,7 @@ export class AuthResponseFactory20161215 implements AuthResponseFactoryInterface
return {
user: this.userProjector.projectSimple(dto.user) as {
uuid: Uuid
uuid: string
email: string
protocolVersion: ProtocolVersion
},

View File

@@ -3,7 +3,7 @@ import {
SessionTokenData,
TokenEncoderInterface,
} from '@standardnotes/security'
import { ProtocolVersion, Uuid } from '@standardnotes/common'
import { ProtocolVersion } from '@standardnotes/common'
import { SessionBody } from '@standardnotes/responses'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
@@ -49,7 +49,7 @@ export class AuthResponseFactory20200115 extends AuthResponseFactory20190520 {
session: sessionPayload,
key_params: this.keyParamsFactory.create(dto.user, true),
user: this.userProjector.projectSimple(dto.user) as {
uuid: Uuid
uuid: string
email: string
protocolVersion: ProtocolVersion
},

View File

@@ -1,6 +1,6 @@
/* istanbul ignore file */
import { JSONString, ProtocolVersion, RoleName, Uuid } from '@standardnotes/common'
import { ProtocolVersion } from '@standardnotes/common'
import {
AccountDeletionRequestedEvent,
UserEmailChangedEvent,
@@ -105,7 +105,7 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
}
}
createWebSocketMessageRequestedEvent(dto: { userUuid: Uuid; message: JSONString }): WebSocketMessageRequestedEvent {
createWebSocketMessageRequestedEvent(dto: { userUuid: string; message: string }): WebSocketMessageRequestedEvent {
return {
type: 'WEB_SOCKET_MESSAGE_REQUESTED',
createdAt: this.timer.getUTCDate(),
@@ -142,7 +142,7 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
}
createPredicateVerifiedEvent(dto: {
userUuid: Uuid
userUuid: string
predicate: Predicate
predicateVerificationResult: PredicateVerificationResult
}): PredicateVerifiedEvent {
@@ -164,10 +164,10 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
createSharedSubscriptionInvitationCanceledEvent(dto: {
inviterEmail: string
inviterSubscriptionId: number
inviterSubscriptionUuid: Uuid
inviterSubscriptionUuid: string
inviteeIdentifier: string
inviteeIdentifierType: InviteeIdentifierType
sharedSubscriptionInvitationUuid: Uuid
sharedSubscriptionInvitationUuid: string
}): SharedSubscriptionInvitationCanceledEvent {
return {
type: 'SHARED_SUBSCRIPTION_INVITATION_CANCELED',
@@ -291,9 +291,9 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
}
createAccountDeletionRequestedEvent(dto: {
userUuid: Uuid
userUuid: string
userCreatedAtTimestamp: number
regularSubscriptionUuid: Uuid | undefined
regularSubscriptionUuid: string | undefined
}): AccountDeletionRequestedEvent {
return {
type: 'ACCOUNT_DELETION_REQUESTED',
@@ -347,7 +347,7 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
}
}
createUserRolesChangedEvent(userUuid: string, email: string, currentRoles: RoleName[]): UserRolesChangedEvent {
createUserRolesChangedEvent(userUuid: string, email: string, currentRoles: string[]): UserRolesChangedEvent {
return {
type: 'USER_ROLES_CHANGED',
createdAt: this.timer.getUTCDate(),

View File

@@ -1,4 +1,4 @@
import { Uuid, RoleName, ProtocolVersion, JSONString } from '@standardnotes/common'
import { ProtocolVersion, JSONString } from '@standardnotes/common'
import { Predicate, PredicateVerificationResult } from '@standardnotes/predicates'
import {
AccountDeletionRequestedEvent,
@@ -23,7 +23,7 @@ import { InviteeIdentifierType } from '../SharedSubscription/InviteeIdentifierTy
export interface DomainEventFactoryInterface {
createUserContentSizeRecalculationRequestedEvent(userUuid: string): UserContentSizeRecalculationRequestedEvent
createWebSocketMessageRequestedEvent(dto: { userUuid: Uuid; message: JSONString }): WebSocketMessageRequestedEvent
createWebSocketMessageRequestedEvent(dto: { userUuid: string; message: JSONString }): WebSocketMessageRequestedEvent
createEmailRequestedEvent(dto: {
userEmail: string
messageIdentifier: string
@@ -50,14 +50,14 @@ export interface DomainEventFactoryInterface {
userHasEmailsMuted: boolean,
): CloudBackupRequestedEvent
createAccountDeletionRequestedEvent(dto: {
userUuid: Uuid
userUuid: string
userCreatedAtTimestamp: number
regularSubscriptionUuid: Uuid | undefined
regularSubscriptionUuid: string | undefined
}): AccountDeletionRequestedEvent
createUserRolesChangedEvent(userUuid: string, email: string, currentRoles: RoleName[]): UserRolesChangedEvent
createUserRolesChangedEvent(userUuid: string, email: string, currentRoles: string[]): UserRolesChangedEvent
createUserEmailChangedEvent(userUuid: string, fromEmail: string, toEmail: string): UserEmailChangedEvent
createUserDisabledSessionUserAgentLoggingEvent(dto: {
userUuid: Uuid
userUuid: string
email: string
}): UserDisabledSessionUserAgentLoggingEvent
createSharedSubscriptionInvitationCreatedEvent(dto: {
@@ -70,13 +70,13 @@ export interface DomainEventFactoryInterface {
createSharedSubscriptionInvitationCanceledEvent(dto: {
inviterEmail: string
inviterSubscriptionId: number
inviterSubscriptionUuid: Uuid
inviterSubscriptionUuid: string
inviteeIdentifier: string
inviteeIdentifierType: InviteeIdentifierType
sharedSubscriptionInvitationUuid: Uuid
sharedSubscriptionInvitationUuid: string
}): SharedSubscriptionInvitationCanceledEvent
createPredicateVerifiedEvent(dto: {
userUuid: Uuid
userUuid: string
predicate: Predicate
predicateVerificationResult: PredicateVerificationResult
}): PredicateVerifiedEvent

View File

@@ -1,12 +1,34 @@
import 'reflect-metadata'
import { Role } from '@standardnotes/security'
import { RoleName, SubscriptionName } from '@standardnotes/common'
import { SubscriptionName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { RoleToSubscriptionMapInterface } from '../Role/RoleToSubscriptionMapInterface'
import { User } from '../User/User'
import { UserSubscription } from '../Subscription/UserSubscription'
jest.mock('@standardnotes/features', () => {
const original = jest.requireActual('@standardnotes/features')
return {
...original,
GetFeatures: jest.fn().mockImplementation(() => [
{
identifier: 'org.standardnotes.theme-autobiography',
permission_name: original.PermissionName.AutobiographyTheme,
expires_at: 555,
},
{
identifier: 'org.standardnotes.bold-editor',
permission_name: original.PermissionName.BoldEditor,
expires_at: 777,
},
]),
}
})
const { GetFeatures } = jest.requireMock('@standardnotes/features')
import { FeatureService } from './FeatureService'
import { Permission, PermissionName } from '@standardnotes/features'
import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface'
@@ -40,10 +62,10 @@ describe('FeatureService', () => {
.fn()
.mockImplementation((subscriptionName: SubscriptionName) => {
if (subscriptionName === SubscriptionName.PlusPlan) {
return RoleName.PlusUser
return RoleName.NAMES.PlusUser
}
if (subscriptionName === SubscriptionName.ProPlan) {
return RoleName.ProUser
return RoleName.NAMES.ProUser
}
return undefined
@@ -67,13 +89,13 @@ describe('FeatureService', () => {
}
role1 = {
name: RoleName.PlusUser,
name: RoleName.NAMES.PlusUser,
uuid: 'role-1-1-1',
permissions: Promise.resolve([permission1, permission3]),
} as jest.Mocked<Role>
role2 = {
name: RoleName.ProUser,
name: RoleName.NAMES.ProUser,
uuid: 'role-2-2-2',
permissions: Promise.resolve([permission2]),
} as jest.Mocked<Role>
@@ -159,9 +181,9 @@ describe('FeatureService', () => {
describe('offline subscribers', () => {
it('should return user features with `expires_at` field', async () => {
const features = await createService().getFeaturesForOfflineUser('test@test.com')
const featuresResponse = await createService().getFeaturesForOfflineUser('test@test.com')
expect(features).toEqual(
expect(featuresResponse.features).toEqual(
expect.arrayContaining([
expect.objectContaining({
identifier: 'org.standardnotes.theme-autobiography',
@@ -174,7 +196,7 @@ describe('FeatureService', () => {
it('should not return user features if a subscription could not be found', async () => {
offlineUserSubscriptionRepository.findByEmail = jest.fn().mockReturnValue([])
expect(await createService().getFeaturesForOfflineUser('test@test.com')).toEqual([])
expect(await createService().getFeaturesForOfflineUser('test@test.com')).toEqual({ features: [], roles: [] })
})
})
@@ -223,7 +245,7 @@ describe('FeatureService', () => {
it('should not return user features if those cannot be find for permissions', async () => {
role1 = {
name: RoleName.CoreUser,
name: RoleName.NAMES.CoreUser,
uuid: 'role-1-1-1',
permissions: Promise.resolve([permission4]),
} as jest.Mocked<Role>
@@ -302,8 +324,26 @@ describe('FeatureService', () => {
name: PermissionName.FilesBeta,
} as jest.Mocked<Permission>
GetFeatures.mockImplementation(() => [
{
identifier: 'org.standardnotes.theme-autobiography',
permission_name: PermissionName.AutobiographyTheme,
expires_at: 555,
},
{
identifier: 'org.standardnotes.bold-editor',
permission_name: PermissionName.BoldEditor,
expires_at: 777,
},
{
permission_name: PermissionName.FilesBeta,
expires_at: undefined,
no_expire: true,
},
])
const nonSubscriptionRole = {
name: RoleName.FilesBetaUser,
name: RoleName.NAMES.FilesBetaUser,
uuid: 'role-files-beta',
permissions: Promise.resolve([nonSubscriptionPermission]),
} as jest.Mocked<Role>
@@ -332,7 +372,6 @@ describe('FeatureService', () => {
expires_at: 777,
}),
expect.objectContaining({
identifier: 'org.standardnotes.files-beta',
expires_at: undefined,
no_expire: true,
}),
@@ -347,7 +386,7 @@ describe('FeatureService', () => {
.mockReturnValueOnce(SubscriptionName.ProPlan)
role2 = {
name: RoleName.ProUser,
name: RoleName.NAMES.ProUser,
uuid: 'role-2-2-2',
permissions: Promise.resolve([permission1, permission2]),
} as jest.Mocked<Role>
@@ -384,7 +423,7 @@ describe('FeatureService', () => {
subscription2.endsAt = lesserExpireAt
role2 = {
name: RoleName.ProUser,
name: RoleName.NAMES.ProUser,
uuid: 'role-2-2-2',
permissions: Promise.resolve([permission1, permission2]),
} as jest.Mocked<Role>

View File

@@ -1,4 +1,4 @@
import { RoleName, SubscriptionName } from '@standardnotes/common'
import { SubscriptionName } from '@standardnotes/common'
import { FeatureDescription, GetFeatures } from '@standardnotes/features'
import { inject, injectable } from 'inversify'
import TYPES from '../../Bootstrap/Types'
@@ -21,7 +21,7 @@ export class FeatureService implements FeatureServiceInterface {
@inject(TYPES.Timer) private timer: TimerInterface,
) {}
async getFeaturesForOfflineUser(email: string): Promise<FeatureDescription[]> {
async getFeaturesForOfflineUser(email: string): Promise<{ features: FeatureDescription[]; roles: Role[] }> {
const userSubscriptions = await this.offlineUserSubscriptionRepository.findByEmail(
email,
this.timer.getTimestampInMicroseconds(),
@@ -34,7 +34,11 @@ export class FeatureService implements FeatureServiceInterface {
}
}
return this.getFeaturesForSubscriptions(userSubscriptions, [...userRolesMap.values()])
const roles = [...userRolesMap.values()]
return {
features: await this.getFeaturesForSubscriptions(userSubscriptions, roles),
roles,
}
}
async getFeaturesForUser(user: User): Promise<Array<FeatureDescription>> {
@@ -117,7 +121,7 @@ export class FeatureService implements FeatureServiceInterface {
...featureForPermission,
expires_at: longestLastingSubscription ? longestLastingSubscription.endsAt : undefined,
no_expire: longestLastingSubscription ? false : true,
role_name: role.name as RoleName,
role_name: role.name,
})
continue

View File

@@ -1,8 +1,9 @@
import { FeatureDescription } from '@standardnotes/features'
import { Role } from '../Role/Role'
import { User } from '../User/User'
export interface FeatureServiceInterface {
getFeaturesForUser(user: User): Promise<Array<FeatureDescription>>
getFeaturesForOfflineUser(email: string): Promise<FeatureDescription[]>
getFeaturesForOfflineUser(email: string): Promise<{ features: FeatureDescription[]; roles: Role[] }>
}

View File

@@ -1,6 +1,7 @@
import 'reflect-metadata'
import { RoleName, SubscriptionName } from '@standardnotes/common'
import { SubscriptionName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { SubscriptionExpiredEvent } from '@standardnotes/domain-events'
import { Logger } from 'winston'
@@ -39,7 +40,7 @@ describe('SubscriptionExpiredEventHandler', () => {
email: 'test@test.com',
roles: Promise.resolve([
{
name: RoleName.ProUser,
name: RoleName.NAMES.ProUser,
},
]),
} as jest.Mocked<User>

View File

@@ -1,4 +1,3 @@
import { SubscriptionName } from '@standardnotes/common'
import { DomainEventHandlerInterface, SubscriptionExpiredEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
@@ -38,10 +37,7 @@ export class SubscriptionExpiredEventHandler implements DomainEventHandlerInterf
await this.removeRoleFromSubscriptionUsers(event.payload.subscriptionId, event.payload.subscriptionName)
}
private async removeRoleFromSubscriptionUsers(
subscriptionId: number,
subscriptionName: SubscriptionName,
): Promise<void> {
private async removeRoleFromSubscriptionUsers(subscriptionId: number, subscriptionName: string): Promise<void> {
const userSubscriptions = await this.userSubscriptionRepository.findBySubscriptionId(subscriptionId)
for (const userSubscription of userSubscriptions) {
await this.roleService.removeUserRole(await userSubscription.user, subscriptionName)

View File

@@ -1,6 +1,7 @@
import 'reflect-metadata'
import { RoleName, SubscriptionName } from '@standardnotes/common'
import { SubscriptionName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { SubscriptionPurchasedEvent } from '@standardnotes/domain-events'
import { Logger } from 'winston'
@@ -47,7 +48,7 @@ describe('SubscriptionPurchasedEventHandler', () => {
email: 'test@test.com',
roles: Promise.resolve([
{
name: RoleName.CoreUser,
name: RoleName.NAMES.CoreUser,
},
]),
} as jest.Mocked<User>

View File

@@ -1,4 +1,3 @@
import { SubscriptionName } from '@standardnotes/common'
import { DomainEventHandlerInterface, SubscriptionPurchasedEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
@@ -65,7 +64,7 @@ export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInte
)
}
private async addUserRole(user: User, subscriptionName: SubscriptionName): Promise<void> {
private async addUserRole(user: User, subscriptionName: string): Promise<void> {
await this.roleService.addUserRole(user, subscriptionName)
}

View File

@@ -1,6 +1,7 @@
import 'reflect-metadata'
import { RoleName, SubscriptionName } from '@standardnotes/common'
import { SubscriptionName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { SubscriptionReassignedEvent } from '@standardnotes/domain-events'
import { Logger } from 'winston'
@@ -45,7 +46,7 @@ describe('SubscriptionReassignedEventHandler', () => {
email: 'test@test.com',
roles: Promise.resolve([
{
name: RoleName.CoreUser,
name: RoleName.NAMES.CoreUser,
},
]),
} as jest.Mocked<User>
@@ -137,7 +138,7 @@ describe('SubscriptionReassignedEventHandler', () => {
email: 'test@test.com',
roles: Promise.resolve([
{
name: RoleName.CoreUser,
name: RoleName.NAMES.CoreUser,
},
]),
},

View File

@@ -1,4 +1,3 @@
import { SubscriptionName } from '@standardnotes/common'
import { DomainEventHandlerInterface, SubscriptionReassignedEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
@@ -62,7 +61,7 @@ export class SubscriptionReassignedEventHandler implements DomainEventHandlerInt
)
}
private async addUserRole(user: User, subscriptionName: SubscriptionName): Promise<void> {
private async addUserRole(user: User, subscriptionName: string): Promise<void> {
await this.roleService.addUserRole(user, subscriptionName)
}

View File

@@ -1,6 +1,7 @@
import 'reflect-metadata'
import { RoleName, SubscriptionName } from '@standardnotes/common'
import { SubscriptionName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { SubscriptionRefundedEvent } from '@standardnotes/domain-events'
import { Logger } from 'winston'
@@ -39,7 +40,7 @@ describe('SubscriptionRefundedEventHandler', () => {
email: 'test@test.com',
roles: Promise.resolve([
{
name: RoleName.ProUser,
name: RoleName.NAMES.ProUser,
},
]),
} as jest.Mocked<User>

View File

@@ -1,4 +1,3 @@
import { SubscriptionName } from '@standardnotes/common'
import { DomainEventHandlerInterface, SubscriptionRefundedEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
@@ -38,10 +37,7 @@ export class SubscriptionRefundedEventHandler implements DomainEventHandlerInter
await this.removeRoleFromSubscriptionUsers(event.payload.subscriptionId, event.payload.subscriptionName)
}
private async removeRoleFromSubscriptionUsers(
subscriptionId: number,
subscriptionName: SubscriptionName,
): Promise<void> {
private async removeRoleFromSubscriptionUsers(subscriptionId: number, subscriptionName: string): Promise<void> {
const userSubscriptions = await this.userSubscriptionRepository.findBySubscriptionId(subscriptionId)
for (const userSubscription of userSubscriptions) {
await this.roleService.removeUserRole(await userSubscription.user, subscriptionName)

View File

@@ -1,6 +1,7 @@
import 'reflect-metadata'
import { RoleName, SubscriptionName } from '@standardnotes/common'
import { SubscriptionName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { SubscriptionRenewedEvent } from '@standardnotes/domain-events'
import * as dayjs from 'dayjs'
import { Logger } from 'winston'
@@ -42,7 +43,7 @@ describe('SubscriptionRenewedEventHandler', () => {
email: 'test@test.com',
roles: Promise.resolve([
{
name: RoleName.CoreUser,
name: RoleName.NAMES.CoreUser,
},
]),
} as jest.Mocked<User>

View File

@@ -4,7 +4,6 @@ import { inject, injectable } from 'inversify'
import TYPES from '../../Bootstrap/Types'
import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface'
import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface'
import { SubscriptionName } from '@standardnotes/common'
import { RoleServiceInterface } from '../Role/RoleServiceInterface'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { Logger } from 'winston'
@@ -61,7 +60,7 @@ export class SubscriptionRenewedEventHandler implements DomainEventHandlerInterf
await this.addRoleToSubscriptionUsers(event.payload.subscriptionId, event.payload.subscriptionName)
}
private async addRoleToSubscriptionUsers(subscriptionId: number, subscriptionName: SubscriptionName): Promise<void> {
private async addRoleToSubscriptionUsers(subscriptionId: number, subscriptionName: string): Promise<void> {
const userSubscriptions = await this.userSubscriptionRepository.findBySubscriptionId(subscriptionId)
for (const userSubscription of userSubscriptions) {
const user = await userSubscription.user

View File

@@ -1,6 +1,7 @@
import 'reflect-metadata'
import { ContentDecoderInterface, RoleName, SubscriptionName } from '@standardnotes/common'
import { ContentDecoderInterface, SubscriptionName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { SubscriptionSyncRequestedEvent } from '@standardnotes/domain-events'
import { Logger } from 'winston'
@@ -55,7 +56,7 @@ describe('SubscriptionSyncRequestedEventHandler', () => {
email: 'test@test.com',
roles: Promise.resolve([
{
name: RoleName.CoreUser,
name: RoleName.NAMES.CoreUser,
},
]),
} as jest.Mocked<User>
@@ -144,7 +145,7 @@ describe('SubscriptionSyncRequestedEventHandler', () => {
email: 'test@test.com',
roles: Promise.resolve([
{
name: RoleName.CoreUser,
name: RoleName.NAMES.CoreUser,
},
]),
uuid: '123',

View File

@@ -4,7 +4,8 @@ import { Logger } from 'winston'
import { User } from '../User/User'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { RoleRepositoryInterface } from '../Role/RoleRepositoryInterface'
import { RoleName, SubscriptionName } from '@standardnotes/common'
import { SubscriptionName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { Role } from '../Role/Role'
import { ClientServiceInterface } from '../Client/ClientServiceInterface'
@@ -39,7 +40,7 @@ describe('RoleService', () => {
beforeEach(() => {
basicRole = {
name: RoleName.CoreUser,
name: RoleName.NAMES.CoreUser,
permissions: Promise.resolve([
{
name: PermissionName.MarkdownBasicEditor,
@@ -48,7 +49,7 @@ describe('RoleService', () => {
} as jest.Mocked<Role>
proRole = {
name: RoleName.ProUser,
name: RoleName.NAMES.ProUser,
permissions: Promise.resolve([
{
name: PermissionName.DailyEmailBackup,
@@ -62,7 +63,7 @@ describe('RoleService', () => {
roleRepository.findOneByName = jest.fn().mockReturnValue(proRole)
roleToSubscriptionMap = {} as jest.Mocked<RoleToSubscriptionMapInterface>
roleToSubscriptionMap.getRoleNameForSubscriptionName = jest.fn().mockReturnValue(RoleName.ProUser)
roleToSubscriptionMap.getRoleNameForSubscriptionName = jest.fn().mockReturnValue(RoleName.NAMES.ProUser)
offlineUserSubscription = {
endsAt: 100,
@@ -97,7 +98,7 @@ describe('RoleService', () => {
it('should add role to user', async () => {
await createService().addUserRole(user, SubscriptionName.ProPlan)
expect(roleRepository.findOneByName).toHaveBeenCalledWith(RoleName.ProUser)
expect(roleRepository.findOneByName).toHaveBeenCalledWith(RoleName.NAMES.ProUser)
user.roles = Promise.resolve([basicRole, proRole])
expect(userRepository.save).toHaveBeenCalledWith(user)
})
@@ -113,7 +114,7 @@ describe('RoleService', () => {
await createService().addUserRole(user, SubscriptionName.ProPlan)
expect(roleRepository.findOneByName).toHaveBeenCalledWith(RoleName.ProUser)
expect(roleRepository.findOneByName).toHaveBeenCalledWith(RoleName.NAMES.ProUser)
expect(userRepository.save).toHaveBeenCalledWith(user)
expect(await user.roles).toHaveLength(2)
})
@@ -142,7 +143,7 @@ describe('RoleService', () => {
it('should set offline role to offline subscription', async () => {
await createService().setOfflineUserRole(offlineUserSubscription)
expect(roleRepository.findOneByName).toHaveBeenCalledWith(RoleName.ProUser)
expect(roleRepository.findOneByName).toHaveBeenCalledWith(RoleName.NAMES.ProUser)
expect(offlineUserSubscriptionRepository.save).toHaveBeenCalledWith({
endsAt: 100,
cancelled: false,

View File

@@ -1,11 +1,10 @@
import { SubscriptionName } from '@standardnotes/common'
import { PermissionName } from '@standardnotes/features'
import { OfflineUserSubscription } from '../Subscription/OfflineUserSubscription'
import { User } from '../User/User'
export interface RoleServiceInterface {
addUserRole(user: User, subscriptionName: SubscriptionName): Promise<void>
addUserRole(user: User, subscriptionName: string): Promise<void>
setOfflineUserRole(offlineUserSubscription: OfflineUserSubscription): Promise<void>
removeUserRole(user: User, subscriptionName: SubscriptionName): Promise<void>
removeUserRole(user: User, subscriptionName: string): Promise<void>
userHasPermission(userUuid: string, permissionName: PermissionName): Promise<boolean>
}

View File

@@ -1,6 +1,7 @@
import 'reflect-metadata'
import { RoleName, SubscriptionName } from '@standardnotes/common'
import { SubscriptionName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { RoleToSubscriptionMap } from './RoleToSubscriptionMap'
import { Role } from './Role'
@@ -9,11 +10,11 @@ describe('RoleToSubscriptionMap', () => {
const createMap = () => new RoleToSubscriptionMap()
it('should return subscription name for role name', () => {
expect(createMap().getSubscriptionNameForRoleName(RoleName.ProUser)).toEqual(SubscriptionName.ProPlan)
expect(createMap().getSubscriptionNameForRoleName(RoleName.NAMES.ProUser)).toEqual(SubscriptionName.ProPlan)
})
it('should return role name for subscription name', () => {
expect(createMap().getRoleNameForSubscriptionName(SubscriptionName.PlusPlan)).toEqual(RoleName.PlusUser)
expect(createMap().getRoleNameForSubscriptionName(SubscriptionName.PlusPlan)).toEqual(RoleName.NAMES.PlusUser)
})
it('should not return role name for subscription name that does not exist', () => {
@@ -23,21 +24,21 @@ describe('RoleToSubscriptionMap', () => {
it('should filter our non subscription roles from an array of roles', () => {
const roles = [
{
name: RoleName.CoreUser,
name: RoleName.NAMES.CoreUser,
} as jest.Mocked<Role>,
{
name: RoleName.FilesBetaUser,
name: RoleName.NAMES.FilesBetaUser,
} as jest.Mocked<Role>,
{
name: RoleName.PlusUser,
name: RoleName.NAMES.PlusUser,
} as jest.Mocked<Role>,
]
expect(createMap().filterNonSubscriptionRoles(roles)).toEqual([
{
name: RoleName.CoreUser,
name: RoleName.NAMES.CoreUser,
},
{
name: RoleName.FilesBetaUser,
name: RoleName.NAMES.FilesBetaUser,
},
])
})
@@ -45,18 +46,18 @@ describe('RoleToSubscriptionMap', () => {
it('should filter our subscription roles from an array of roles', () => {
const roles = [
{
name: RoleName.CoreUser,
name: RoleName.NAMES.CoreUser,
} as jest.Mocked<Role>,
{
name: RoleName.FilesBetaUser,
name: RoleName.NAMES.FilesBetaUser,
} as jest.Mocked<Role>,
{
name: RoleName.PlusUser,
name: RoleName.NAMES.PlusUser,
} as jest.Mocked<Role>,
]
expect(createMap().filterSubscriptionRoles(roles)).toEqual([
{
name: RoleName.PlusUser,
name: RoleName.NAMES.PlusUser,
},
])
})

View File

@@ -1,4 +1,5 @@
import { RoleName, SubscriptionName } from '@standardnotes/common'
import { SubscriptionName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { injectable } from 'inversify'
import { Role } from './Role'
@@ -6,26 +7,26 @@ import { RoleToSubscriptionMapInterface } from './RoleToSubscriptionMapInterface
@injectable()
export class RoleToSubscriptionMap implements RoleToSubscriptionMapInterface {
private readonly roleNameToSubscriptionNameMap = new Map<RoleName, SubscriptionName>([
[RoleName.PlusUser, SubscriptionName.PlusPlan],
[RoleName.ProUser, SubscriptionName.ProPlan],
private readonly roleNameToSubscriptionNameMap = new Map<string, SubscriptionName>([
[RoleName.NAMES.PlusUser, SubscriptionName.PlusPlan],
[RoleName.NAMES.ProUser, SubscriptionName.ProPlan],
])
private readonly nonSubscriptionRoles = [RoleName.CoreUser, RoleName.FilesBetaUser]
private readonly nonSubscriptionRoles = [RoleName.NAMES.CoreUser, RoleName.NAMES.FilesBetaUser]
filterNonSubscriptionRoles(roles: Role[]): Array<Role> {
return roles.filter((role) => this.nonSubscriptionRoles.includes(role.name as RoleName))
return roles.filter((role) => this.nonSubscriptionRoles.includes(role.name))
}
filterSubscriptionRoles(roles: Role[]): Array<Role> {
return roles.filter((role) => !this.nonSubscriptionRoles.includes(role.name as RoleName))
return roles.filter((role) => !this.nonSubscriptionRoles.includes(role.name))
}
getSubscriptionNameForRoleName(roleName: RoleName): SubscriptionName | undefined {
getSubscriptionNameForRoleName(roleName: string): SubscriptionName | undefined {
return this.roleNameToSubscriptionNameMap.get(roleName)
}
getRoleNameForSubscriptionName(subscriptionName: SubscriptionName): RoleName | undefined {
getRoleNameForSubscriptionName(subscriptionName: SubscriptionName): string | undefined {
for (const [roleNameItem, subscriptionNameItem] of this.roleNameToSubscriptionNameMap) {
if (subscriptionNameItem === subscriptionName) {
return roleNameItem

View File

@@ -1,9 +1,9 @@
import { RoleName, SubscriptionName } from '@standardnotes/common'
import { SubscriptionName } from '@standardnotes/common'
import { Role } from './Role'
export interface RoleToSubscriptionMapInterface {
filterNonSubscriptionRoles(roles: Role[]): Array<Role>
filterSubscriptionRoles(roles: Role[]): Array<Role>
getSubscriptionNameForRoleName(roleName: RoleName): SubscriptionName | undefined
getRoleNameForSubscriptionName(subscriptionName: SubscriptionName): RoleName | undefined
getSubscriptionNameForRoleName(roleName: string): SubscriptionName | undefined
getRoleNameForSubscriptionName(subscriptionName: SubscriptionName): string | undefined
}

View File

@@ -1,4 +1,3 @@
import { Uuid } from '@standardnotes/common'
import { RevokedSession } from './RevokedSession'
export interface RevokedSessionRepositoryInterface {
@@ -6,5 +5,5 @@ export interface RevokedSessionRepositoryInterface {
findAllByUserUuid(userUuid: string): Promise<Array<RevokedSession>>
save(revokedSession: RevokedSession): Promise<RevokedSession>
remove(revokedSession: RevokedSession): Promise<RevokedSession>
clearUserAgentByUserUuid(userUuid: Uuid): Promise<void>
clearUserAgentByUserUuid(userUuid: string): Promise<void>
}

View File

@@ -1,4 +1,3 @@
import { Uuid } from '@standardnotes/common'
import { Session } from './Session'
export interface SessionRepositoryInterface {
@@ -12,5 +11,5 @@ export interface SessionRepositoryInterface {
updatedTokenExpirationDates(uuid: string, accessExpiration: Date, refreshExpiration: Date): Promise<void>
save(session: Session): Promise<Session>
remove(session: Session): Promise<Session>
clearUserAgentByUserUuid(userUuid: Uuid): Promise<void>
clearUserAgentByUserUuid(userUuid: string): Promise<void>
}

View File

@@ -7,7 +7,6 @@ import { TimerInterface } from '@standardnotes/time'
import { Logger } from 'winston'
import { LogSessionUserAgentOption, SettingName } from '@standardnotes/settings'
import { SessionBody } from '@standardnotes/responses'
import { Uuid } from '@standardnotes/common'
import { CryptoNode } from '@standardnotes/sncrypto-node'
import TYPES from '../../Bootstrap/Types'
@@ -226,7 +225,7 @@ export class SessionService implements SessionServiceInterface {
return this.revokedSessionRepository.save(revokedSession)
}
async deleteSessionByToken(token: string): Promise<Uuid | null> {
async deleteSessionByToken(token: string): Promise<string | null> {
const session = await this.getSessionFromToken(token)
if (session) {

View File

@@ -1,4 +1,3 @@
import { Uuid } from '@standardnotes/common'
import { SessionBody } from '@standardnotes/responses'
import { User } from '../User/User'
import { RevokedSession } from './RevokedSession'
@@ -21,7 +20,7 @@ export interface SessionServiceInterface {
getSessionFromToken(token: string): Promise<Session | undefined>
getRevokedSessionFromToken(token: string): Promise<RevokedSession | null>
markRevokedSessionAsReceived(revokedSession: RevokedSession): Promise<RevokedSession>
deleteSessionByToken(token: string): Promise<Uuid | null>
deleteSessionByToken(token: string): Promise<string | null>
isRefreshTokenValid(session: Session, token: string): boolean
getDeviceInfo(session: Session): string
getOperatingSystemInfoFromUserAgent(userAgent: string): string

View File

@@ -1,6 +1,4 @@
import { Uuid } from '@standardnotes/common'
export type DeleteSettingDto = {
settingName: string
userUuid: Uuid
userUuid: string
}

View File

@@ -1,8 +1,7 @@
import { Uuid } from '@standardnotes/common'
import { SettingName } from '@standardnotes/settings'
export type FindSettingDTO = {
userUuid: string
settingName: SettingName
settingUuid?: Uuid
settingUuid?: string
}

View File

@@ -1,9 +1,8 @@
import { Uuid } from '@standardnotes/common'
import { SubscriptionSettingName } from '@standardnotes/settings'
export type FindSubscriptionSettingDTO = {
userUuid: Uuid
userSubscriptionUuid: Uuid
userUuid: string
userSubscriptionUuid: string
subscriptionSettingName: SubscriptionSettingName
settingUuid?: Uuid
settingUuid?: string
}

View File

@@ -1,7 +1,6 @@
import { Uuid } from '@standardnotes/common'
import { Setting } from './Setting'
import { SubscriptionSetting } from './SubscriptionSetting'
export interface SettingDecrypterInterface {
decryptSettingValue(setting: Setting | SubscriptionSetting, userUuid: Uuid): Promise<string | null>
decryptSettingValue(setting: Setting | SubscriptionSetting, userUuid: string): Promise<string | null>
}

View File

@@ -1,4 +1,4 @@
import { SubscriptionName, Uuid } from '@standardnotes/common'
import { SubscriptionName } from '@standardnotes/common'
import { SubscriptionSettingName } from '@standardnotes/settings'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
@@ -34,7 +34,7 @@ export class SubscriptionSettingService implements SubscriptionSettingServiceInt
async applyDefaultSubscriptionSettingsForSubscription(
userSubscription: UserSubscription,
subscriptionName: SubscriptionName,
userUuid: Uuid,
userUuid: string,
): Promise<void> {
const defaultSettingsWithValues =
await this.subscriptionSettingAssociationService.getDefaultSettingsAndValuesForSubscriptionName(subscriptionName)
@@ -129,8 +129,8 @@ export class SubscriptionSettingService implements SubscriptionSettingServiceInt
private async findPreviousSubscriptionSetting(
settingName: SubscriptionSettingName,
currentUserSubscriptionUuid: Uuid,
userUuid: Uuid,
currentUserSubscriptionUuid: string,
userUuid: string,
): Promise<SubscriptionSetting | null> {
const userSubscriptions = await this.userSubscriptionRepository.findByUserUuid(userUuid)
const previousSubscriptions = userSubscriptions.filter(

View File

@@ -1,4 +1,3 @@
import { SubscriptionName, Uuid } from '@standardnotes/common'
import { UserSubscription } from '../Subscription/UserSubscription'
import { CreateOrReplaceSubscriptionSettingDTO } from './CreateOrReplaceSubscriptionSettingDTO'
@@ -9,8 +8,8 @@ import { SubscriptionSetting } from './SubscriptionSetting'
export interface SubscriptionSettingServiceInterface {
applyDefaultSubscriptionSettingsForSubscription(
userSubscription: UserSubscription,
subscriptionName: SubscriptionName,
userUuid: Uuid,
subscriptionName: string,
userUuid: string,
): Promise<void>
createOrReplace(dto: CreateOrReplaceSubscriptionSettingDTO): Promise<CreateOrReplaceSubscriptionSettingResponse>
findSubscriptionSettingWithDecryptedValue(dto: FindSubscriptionSettingDTO): Promise<SubscriptionSetting | null>

View File

@@ -1,6 +1,7 @@
import 'reflect-metadata'
import { RoleName, SubscriptionName } from '@standardnotes/common'
import { SubscriptionName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { SubscriptionSettingName } from '@standardnotes/settings'
import { PermissionName } from '@standardnotes/features'
@@ -20,7 +21,7 @@ describe('SubscriptionSettingsAssociationService', () => {
beforeEach(() => {
roleToSubscriptionMap = {} as jest.Mocked<RoleToSubscriptionMapInterface>
roleToSubscriptionMap.getRoleNameForSubscriptionName = jest.fn().mockReturnValue(RoleName.PlusUser)
roleToSubscriptionMap.getRoleNameForSubscriptionName = jest.fn().mockReturnValue(RoleName.NAMES.PlusUser)
role = {} as jest.Mocked<Role>

View File

@@ -1,4 +1,4 @@
import { RoleName, SubscriptionName } from '@standardnotes/common'
import { SubscriptionName } from '@standardnotes/common'
import { PermissionName } from '@standardnotes/features'
import { SubscriptionSettingName } from '@standardnotes/settings'
import { inject, injectable } from 'inversify'
@@ -65,7 +65,7 @@ export class SubscriptionSettingsAssociationService implements SubscriptionSetti
async getFileUploadLimit(subscriptionName: SubscriptionName): Promise<number> {
const roleName = this.roleToSubscriptionMap.getRoleNameForSubscriptionName(subscriptionName)
const role = await this.roleRepository.findOneByName(roleName as RoleName)
const role = await this.roleRepository.findOneByName(roleName as string)
if (role === null) {
throw new Error(`Could not find role with name: ${roleName}`)
}

View File

@@ -1,15 +1,14 @@
import { Uuid } from '@standardnotes/common'
import { InvitationStatus } from './InvitationStatus'
import { SharedSubscriptionInvitation } from './SharedSubscriptionInvitation'
export interface SharedSubscriptionInvitationRepositoryInterface {
save(sharedSubscriptionInvitation: SharedSubscriptionInvitation): Promise<SharedSubscriptionInvitation>
findOneByUuidAndStatus(uuid: Uuid, status: InvitationStatus): Promise<SharedSubscriptionInvitation | null>
findOneByUuid(uuid: Uuid): Promise<SharedSubscriptionInvitation | null>
findOneByUuidAndStatus(uuid: string, status: InvitationStatus): Promise<SharedSubscriptionInvitation | null>
findOneByUuid(uuid: string): Promise<SharedSubscriptionInvitation | null>
findByInviterEmail(inviterEmail: string): Promise<SharedSubscriptionInvitation[]>
findOneByInviteeAndInviterEmail(
inviteeEmail: string,
inviterEmail: string,
): Promise<SharedSubscriptionInvitation | null>
countByInviterEmailAndStatus(inviterEmail: Uuid, statuses: InvitationStatus[]): Promise<number>
countByInviterEmailAndStatus(inviterEmail: string, statuses: InvitationStatus[]): Promise<number>
}

View File

@@ -1,8 +1,6 @@
import { Uuid } from '@standardnotes/common'
import { SubscriptionToken } from './SubscriptionToken'
export interface SubscriptionTokenRepositoryInterface {
save(subscriptionToken: SubscriptionToken): Promise<boolean>
getUserUuidByToken(token: string): Promise<Uuid | undefined>
getUserUuidByToken(token: string): Promise<string | undefined>
}

View File

@@ -1,13 +1,12 @@
import { Uuid } from '@standardnotes/common'
import { UserSubscription } from './UserSubscription'
import { UserSubscriptionType } from './UserSubscriptionType'
export interface UserSubscriptionRepositoryInterface {
findOneByUuid(uuid: Uuid): Promise<UserSubscription | null>
countByUserUuid(userUuid: Uuid): Promise<number>
findOneByUserUuid(userUuid: Uuid): Promise<UserSubscription | null>
findByUserUuid(userUuid: Uuid): Promise<UserSubscription[]>
findOneByUserUuidAndSubscriptionId(userUuid: Uuid, subscriptionId: number): Promise<UserSubscription | null>
findOneByUuid(uuid: string): Promise<UserSubscription | null>
countByUserUuid(userUuid: string): Promise<number>
findOneByUserUuid(userUuid: string): Promise<UserSubscription | null>
findByUserUuid(userUuid: string): Promise<UserSubscription[]>
findOneByUserUuidAndSubscriptionId(userUuid: string, subscriptionId: number): Promise<UserSubscription | null>
findBySubscriptionIdAndType(subscriptionId: number, type: UserSubscriptionType): Promise<UserSubscription[]>
findBySubscriptionId(subscriptionId: number): Promise<UserSubscription[]>
updateEndsAt(subscriptionId: number, endsAt: number, updatedAt: number): Promise<void>

View File

@@ -1,4 +1,3 @@
import { Uuid } from '@standardnotes/common'
import { inject, injectable } from 'inversify'
import TYPES from '../../Bootstrap/Types'
@@ -21,7 +20,7 @@ export class UserSubscriptionService implements UserSubscriptionServiceInterface
return this.findRegularSubscription(userSubscription)
}
async findRegularSubscriptionForUuid(uuid: Uuid): Promise<FindRegularSubscriptionResponse> {
async findRegularSubscriptionForUuid(uuid: string): Promise<FindRegularSubscriptionResponse> {
const userSubscription = await this.userSubscriptionRepository.findOneByUuid(uuid)
return this.findRegularSubscription(userSubscription)

View File

@@ -1,7 +1,6 @@
import { Uuid } from '@standardnotes/common'
import { FindRegularSubscriptionResponse } from './FindRegularSubscriptionResponse'
export interface UserSubscriptionServiceInterface {
findRegularSubscriptionForUuid(uuid: Uuid): Promise<FindRegularSubscriptionResponse>
findRegularSubscriptionForUserUuid(userUuid: Uuid): Promise<FindRegularSubscriptionResponse>
findRegularSubscriptionForUuid(uuid: string): Promise<FindRegularSubscriptionResponse>
findRegularSubscriptionForUserUuid(userUuid: string): Promise<FindRegularSubscriptionResponse>
}

View File

@@ -1,6 +1,7 @@
import 'reflect-metadata'
import { RoleName, SubscriptionName } from '@standardnotes/common'
import { SubscriptionName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { TimerInterface } from '@standardnotes/time'
import { RoleServiceInterface } from '../../Role/RoleServiceInterface'
@@ -42,7 +43,7 @@ describe('AcceptSharedSubscriptionInvitation', () => {
email: 'test@test.com',
roles: Promise.resolve([
{
name: RoleName.CoreUser,
name: RoleName.NAMES.CoreUser,
},
]),
} as jest.Mocked<User>

View File

@@ -1,6 +1,6 @@
import 'reflect-metadata'
import { RoleName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { SubscriptionTokenRepositoryInterface } from '../../Subscription/SubscriptionTokenRepositoryInterface'
import { User } from '../../User/User'
@@ -20,7 +20,7 @@ describe('AuthenticateSubscriptionToken', () => {
subscriptionTokenRepository.getUserUuidByToken = jest.fn().mockReturnValue('1-2-3')
user = {
roles: Promise.resolve([{ name: RoleName.CoreUser }]),
roles: Promise.resolve([{ name: RoleName.NAMES.CoreUser }]),
} as jest.Mocked<User>
userRepository = {} as jest.Mocked<UserRepositoryInterface>

View File

@@ -1,6 +1,7 @@
import 'reflect-metadata'
import { RoleName, SubscriptionName } from '@standardnotes/common'
import { SubscriptionName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { TimerInterface } from '@standardnotes/time'
import { RoleServiceInterface } from '../../Role/RoleServiceInterface'
@@ -49,7 +50,7 @@ describe('CancelSharedSubscriptionInvitation', () => {
email: 'test@test.com',
roles: Promise.resolve([
{
name: RoleName.CoreUser,
name: RoleName.NAMES.CoreUser,
},
]),
} as jest.Mocked<User>

View File

@@ -1,6 +1,4 @@
import { Uuid } from '@standardnotes/common'
export type CancelSharedSubscriptionInvitationDTO = {
sharedSubscriptionInvitationUuid: Uuid
sharedSubscriptionInvitationUuid: string
inviterEmail: string
}

View File

@@ -1,4 +1,3 @@
import { RoleName } from '@standardnotes/common'
import { TokenEncoderInterface, CrossServiceTokenData } from '@standardnotes/security'
import { inject, injectable } from 'inversify'
@@ -78,7 +77,7 @@ export class CreateCrossServiceToken implements UseCaseInterface {
>this.sessionProjector.projectSimple(session)
}
private projectRoles(roles: Array<Role>): Array<{ uuid: string; name: RoleName }> {
return roles.map((role) => <{ uuid: string; name: RoleName }>this.roleProjector.projectSimple(role))
private projectRoles(roles: Array<Role>): Array<{ uuid: string; name: string }> {
return roles.map((role) => <{ uuid: string; name: string }>this.roleProjector.projectSimple(role))
}
}

View File

@@ -1,4 +1,4 @@
import { Either, Uuid } from '@standardnotes/common'
import { Either } from '@standardnotes/common'
import { Session } from '../../Session/Session'
import { User } from '../../User/User'
@@ -8,6 +8,6 @@ export type CreateCrossServiceTokenDTO = Either<
session?: Session
},
{
userUuid: Uuid
userUuid: string
}
>

View File

@@ -1,7 +1,5 @@
import { Uuid } from '@standardnotes/common'
export type DeleteSettingDto = {
userUuid: Uuid
userUuid: string
settingName: string
uuid?: string
timestamp?: number

View File

@@ -1,9 +1,7 @@
import { Uuid } from '@standardnotes/common'
export type DeleteSettingResponse =
| {
success: true
userUuid: Uuid
userUuid: string
settingName: string
}
| {

View File

@@ -1,7 +1,5 @@
import { Uuid } from '@standardnotes/common'
export type GetSettingDto = {
userUuid: Uuid
userUuid: string
settingName: string
allowSensitiveRetrieval?: boolean
}

View File

@@ -1,11 +1,9 @@
import { Uuid } from '@standardnotes/common'
import { SimpleSetting } from '../../Setting/SimpleSetting'
export type GetSettingResponse =
| {
success: true
userUuid: Uuid
userUuid: string
setting: SimpleSetting
}
| {

View File

@@ -1,7 +1,5 @@
import { Uuid } from '@standardnotes/common'
export type GetSettingsDto = {
userUuid: Uuid
userUuid: string
settingName?: string
allowSensitiveRetrieval?: boolean
updatedAfter?: number

View File

@@ -1,11 +1,9 @@
import { Uuid } from '@standardnotes/common'
import { SimpleSetting } from '../../Setting/SimpleSetting'
export type GetSettingsResponse =
| {
success: true
userUuid: Uuid
userUuid: string
settings: SimpleSetting[]
}
| {

View File

@@ -1,8 +1,7 @@
import { Uuid } from '@standardnotes/common'
import { SubscriptionSettingName } from '@standardnotes/settings'
export type GetSubscriptionSettingDTO = {
userUuid: Uuid
userUuid: string
subscriptionSettingName: SubscriptionSettingName
allowSensitiveRetrieval?: boolean
}

View File

@@ -1,5 +1,7 @@
import 'reflect-metadata'
import { FeatureDescription } from '@standardnotes/features'
import { RoleName } from '@standardnotes/domain-core'
import { GetUserFeatures } from './GetUserFeatures'
import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
import { User } from '../../User/User'
@@ -21,7 +23,9 @@ describe('GetUserFeatures', () => {
feature1 = { name: 'foobar' } as jest.Mocked<FeatureDescription>
featureService = {} as jest.Mocked<FeatureServiceInterface>
featureService.getFeaturesForUser = jest.fn().mockReturnValue([feature1])
featureService.getFeaturesForOfflineUser = jest.fn().mockReturnValue([feature1])
featureService.getFeaturesForOfflineUser = jest
.fn()
.mockReturnValue({ features: [feature1], roles: [RoleName.NAMES.ProUser] })
})
it('should fail if a user is not found', async () => {
@@ -50,11 +54,8 @@ describe('GetUserFeatures', () => {
it('should return offline user features', async () => {
expect(await createUseCase().execute({ email: 'test@test.com', offline: true })).toEqual({
success: true,
features: [
{
name: 'foobar',
},
],
features: [{ name: 'foobar' }],
offlineRoles: [RoleName.NAMES.ProUser],
})
})
})

View File

@@ -15,11 +15,12 @@ export class GetUserFeatures implements UseCaseInterface {
async execute(dto: GetUserFeaturesDto): Promise<GetUserFeaturesResponse> {
if (dto.offline) {
const userFeatures = await this.featureService.getFeaturesForOfflineUser(dto.email)
const { features, roles } = await this.featureService.getFeaturesForOfflineUser(dto.email)
return {
success: true,
features: userFeatures,
features,
offlineRoles: roles,
}
}

View File

@@ -1,8 +1,6 @@
import { Uuid } from '@standardnotes/common'
export type GetUserFeaturesDto =
| {
userUuid: Uuid
userUuid: string
offline: false
}
| {

View File

@@ -1,9 +1,12 @@
import { FeatureDescription } from '@standardnotes/features'
import { Role } from './../../Role/Role'
export type GetUserFeaturesResponse =
| {
success: true
features: FeatureDescription[]
offlineRoles?: Role[]
userUuid?: string
}
| {

View File

@@ -1,5 +1,3 @@
import { Uuid } from '@standardnotes/common'
export type GetUserSubscriptionDto = {
userUuid: Uuid
userUuid: string
}

View File

@@ -12,7 +12,7 @@ import { SharedSubscriptionInvitationRepositoryInterface } from '../../SharedSub
import { InviteToSharedSubscription } from './InviteToSharedSubscription'
import { UserSubscriptionRepositoryInterface } from '../../Subscription/UserSubscriptionRepositoryInterface'
import { UserSubscription } from '../../Subscription/UserSubscription'
import { RoleName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { UserSubscriptionType } from '../../Subscription/UserSubscriptionType'
import { SharedSubscriptionInvitation } from '../../SharedSubscription/SharedSubscriptionInvitation'
import { InvitationStatus } from '../../SharedSubscription/InvitationStatus'
@@ -65,7 +65,7 @@ describe('InviteToSharedSubscription', () => {
inviteeIdentifier: 'invitee@test.te',
inviterUuid: '1-2-3',
inviterEmail: 'inviter@test.te',
inviterRoles: [RoleName.ProUser],
inviterRoles: [RoleName.NAMES.ProUser],
})
expect(sharedSubscriptionInvitationRepository.save).not.toHaveBeenCalled()
@@ -80,7 +80,7 @@ describe('InviteToSharedSubscription', () => {
inviteeIdentifier: 'invitee@test.te',
inviterUuid: '1-2-3',
inviterEmail: 'inviter@test.te',
inviterRoles: [RoleName.PlusUser],
inviterRoles: [RoleName.NAMES.PlusUser],
}),
).toEqual({
success: false,
@@ -100,7 +100,7 @@ describe('InviteToSharedSubscription', () => {
inviteeIdentifier: 'invitee@test.te',
inviterUuid: '1-2-3',
inviterEmail: 'inviter@test.te',
inviterRoles: [RoleName.ProUser],
inviterRoles: [RoleName.NAMES.ProUser],
}),
).toEqual({
success: false,
@@ -117,7 +117,7 @@ describe('InviteToSharedSubscription', () => {
inviteeIdentifier: 'invitee@test.te',
inviterUuid: '1-2-3',
inviterEmail: 'inviter@test.te',
inviterRoles: [RoleName.ProUser],
inviterRoles: [RoleName.NAMES.ProUser],
})
expect(sharedSubscriptionInvitationRepository.save).toHaveBeenCalledWith({
@@ -146,7 +146,7 @@ describe('InviteToSharedSubscription', () => {
inviteeIdentifier: 'a75a31ce95365904ef0e0a8e6cefc1f5e99adfef81bbdb6d4499eeb10ae0ff67',
inviterEmail: 'inviter@test.te',
inviterUuid: '1-2-3',
inviterRoles: [RoleName.ProUser],
inviterRoles: [RoleName.NAMES.ProUser],
})
expect(sharedSubscriptionInvitationRepository.save).toHaveBeenCalledWith({
@@ -180,7 +180,7 @@ describe('InviteToSharedSubscription', () => {
inviteeIdentifier: 'invitee@test.te',
inviterUuid: '1-2-3',
inviterEmail: 'inviter@test.te',
inviterRoles: [RoleName.ProUser],
inviterRoles: [RoleName.NAMES.ProUser],
})
expect(sharedSubscriptionInvitationRepository.save).not.toHaveBeenCalled()
@@ -200,7 +200,7 @@ describe('InviteToSharedSubscription', () => {
inviteeIdentifier: 'invitee@test.te',
inviterUuid: '1-2-3',
inviterEmail: 'inviter@test.te',
inviterRoles: [RoleName.ProUser],
inviterRoles: [RoleName.NAMES.ProUser],
}),
).toEqual({
success: false,
@@ -222,7 +222,7 @@ describe('InviteToSharedSubscription', () => {
inviteeIdentifier: 'invitee@test.te',
inviterUuid: '1-2-3',
inviterEmail: 'inviter@test.te',
inviterRoles: [RoleName.ProUser],
inviterRoles: [RoleName.NAMES.ProUser],
}),
).toEqual({
success: true,

View File

@@ -1,6 +1,5 @@
import { RoleName } from '@standardnotes/common'
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
import { EmailLevel } from '@standardnotes/domain-core'
import { EmailLevel, RoleName } from '@standardnotes/domain-core'
import { TimerInterface } from '@standardnotes/time'
import { inject, injectable } from 'inversify'
@@ -32,7 +31,7 @@ export class InviteToSharedSubscription implements UseCaseInterface {
) {}
async execute(dto: InviteToSharedSubscriptionDTO): Promise<InviteToSharedSubscriptionResult> {
if (!dto.inviterRoles.includes(RoleName.ProUser)) {
if (!dto.inviterRoles.includes(RoleName.NAMES.ProUser)) {
return {
success: false,
}

View File

@@ -1,8 +1,6 @@
import { RoleName, Uuid } from '@standardnotes/common'
export type InviteToSharedSubscriptionDTO = {
inviterEmail: string
inviterUuid: Uuid
inviterRoles: RoleName[]
inviterUuid: string
inviterRoles: string[]
inviteeIdentifier: string
}

View File

@@ -1,9 +1,7 @@
import { Uuid } from '@standardnotes/common'
export type InviteToSharedSubscriptionResult =
| {
success: true
sharedSubscriptionInvitationUuid: Uuid
sharedSubscriptionInvitationUuid: string
}
| {
success: false

View File

@@ -1,7 +1,7 @@
import { UserRequestType, Uuid } from '@standardnotes/common'
import { UserRequestType } from '@standardnotes/common'
export type ProcessUserRequestDTO = {
userUuid: Uuid
userUuid: string
userEmail: string
requestType: UserRequestType
}

View File

@@ -1,5 +1,5 @@
import * as bcrypt from 'bcryptjs'
import { RoleName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { ApiVersion } from '@standardnotes/api'
import { v4 as uuidv4 } from 'uuid'
@@ -63,7 +63,7 @@ export class Register implements UseCaseInterface {
user.encryptedServerKey = await this.crypter.generateEncryptedUserServerKey()
user.serverEncryptionVersion = User.DEFAULT_ENCRYPTION_VERSION
const defaultRole = await this.roleRepository.findOneByName(RoleName.CoreUser)
const defaultRole = await this.roleRepository.findOneByName(RoleName.NAMES.CoreUser)
if (defaultRole) {
user.roles = Promise.resolve([defaultRole])
}

View File

@@ -1,8 +1,6 @@
import { Uuid } from '@standardnotes/common'
import { SettingProps } from '../../Setting/SettingProps'
export type UpdateSettingDto = {
userUuid: Uuid
userUuid: string
props: SettingProps
}

View File

@@ -1,4 +1,3 @@
import { Uuid } from '@standardnotes/common'
import { PredicateName, PredicateVerificationResult } from '@standardnotes/predicates'
import { EmailBackupFrequency, SettingName } from '@standardnotes/settings'
import { inject, injectable } from 'inversify'
@@ -33,13 +32,13 @@ export class VerifyPredicate implements UseCaseInterface {
}
}
private async hasUserBoughtASubscription(userUuid: Uuid): Promise<boolean> {
private async hasUserBoughtASubscription(userUuid: string): Promise<boolean> {
const subscription = await this.userSubscriptionRepository.findOneByUserUuid(userUuid)
return subscription !== null
}
private async hasUserEnabledEmailBackups(userUuid: Uuid): Promise<boolean> {
private async hasUserEnabledEmailBackups(userUuid: string): Promise<boolean> {
const setting = await this.settingRepository.findOneByNameAndUserUuid(SettingName.EmailBackupFrequency, userUuid)
if (setting === null || setting.value === EmailBackupFrequency.Disabled) {

View File

@@ -1,7 +1,6 @@
import { Uuid } from '@standardnotes/common'
import { Predicate } from '@standardnotes/predicates'
export type VerifyPredicateDTO = {
predicate: Predicate
userUuid: Uuid
userUuid: string
}

View File

@@ -1,4 +1,3 @@
import { Uuid } from '@standardnotes/common'
import { TimerInterface } from '@standardnotes/time'
import { inject, injectable } from 'inversify'
import { Repository } from 'typeorm'
@@ -34,7 +33,7 @@ export class MySQLUserSubscriptionRepository implements UserSubscriptionReposito
.getMany()
}
async countByUserUuid(userUuid: Uuid): Promise<number> {
async countByUserUuid(userUuid: string): Promise<number> {
return await this.ormRepository
.createQueryBuilder()
.where('user_uuid = :user_uuid', {
@@ -47,7 +46,7 @@ export class MySQLUserSubscriptionRepository implements UserSubscriptionReposito
return this.ormRepository.save(subscription)
}
async findOneByUserUuidAndSubscriptionId(userUuid: Uuid, subscriptionId: number): Promise<UserSubscription | null> {
async findOneByUserUuidAndSubscriptionId(userUuid: string, subscriptionId: number): Promise<UserSubscription | null> {
return await this.ormRepository
.createQueryBuilder()
.where('user_uuid = :userUuid AND subscription_id = :subscriptionId', {
@@ -78,7 +77,7 @@ export class MySQLUserSubscriptionRepository implements UserSubscriptionReposito
.getMany()
}
async findOneByUuid(uuid: Uuid): Promise<UserSubscription | null> {
async findOneByUuid(uuid: string): Promise<UserSubscription | null> {
return await this.ormRepository
.createQueryBuilder()
.where('uuid = :uuid', {
@@ -87,7 +86,7 @@ export class MySQLUserSubscriptionRepository implements UserSubscriptionReposito
.getOne()
}
async findOneByUserUuid(userUuid: Uuid): Promise<UserSubscription | null> {
async findOneByUserUuid(userUuid: string): Promise<UserSubscription | null> {
const subscriptions = await this.ormRepository
.createQueryBuilder()
.where('user_uuid = :user_uuid', {

View File

@@ -1,4 +1,3 @@
import { RoleName } from '@standardnotes/common'
import { inject, injectable } from 'inversify'
import TYPES from '../../Bootstrap/Types'
@@ -18,7 +17,7 @@ export class WebSocketsClientService implements ClientServiceInterface {
const event = this.domainEventFactory.createUserRolesChangedEvent(
user.uuid,
user.email,
(await user.roles).map((role) => role.name) as RoleName[],
(await user.roles).map((role) => role.name),
)
await this.domainEventPublisher.publish(

View File

@@ -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.
## [1.46.3](https://github.com/standardnotes/server/compare/@standardnotes/common@1.46.2...@standardnotes/common@1.46.3) (2023-01-19)
**Note:** Version bump only for package @standardnotes/common
## [1.46.2](https://github.com/standardnotes/server/compare/@standardnotes/common@1.46.1...@standardnotes/common@1.46.2) (2023-01-19)
**Note:** Version bump only for package @standardnotes/common
## [1.46.1](https://github.com/standardnotes/server/compare/@standardnotes/common@1.46.0...@standardnotes/common@1.46.1) (2022-11-25)
### Bug Fixes

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/common",
"version": "1.46.1",
"version": "1.46.3",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -1 +0,0 @@
export type Uuid = string

View File

@@ -1,4 +0,0 @@
/* istanbul ignore file */
import { RoleName } from './RoleName'
export const PaidRoles = [RoleName.CoreUser, RoleName.PlusUser, RoleName.ProUser]

View File

@@ -1,7 +0,0 @@
/* istanbul ignore file */
export enum RoleName {
CoreUser = 'CORE_USER',
PlusUser = 'PLUS_USER',
ProUser = 'PRO_USER',
FilesBetaUser = 'FILES_BETA_USER',
}

View File

@@ -1,34 +0,0 @@
import { UuidValidator } from './UuidValidator'
describe('UuidValidator', () => {
const createValidator = () => new UuidValidator()
const validUuids = [
'2221101c-1da9-4d2b-9b32-b8be2a8d1c82',
'c08f2f29-a74b-42b4-aefd-98af9832391c',
'b453fa64-1493-443b-b5bb-bca7b9c696c7',
]
const invalidUuids = [
123,
'someone@127.0.0.1',
'',
null,
'b453fa64-1493-443b-b5bb-ca7b9c696c7',
'c08f*f29-a74b-42b4-aefd-98af9832391c',
'c08f*f29-a74b-42b4-aefd-98af9832391c',
'../../escaped.sh',
]
it('should validate proper uuids', () => {
for (const validUuid of validUuids) {
expect(createValidator().validate(validUuid)).toBeTruthy()
}
})
it('should not validate invalid uuids', () => {
for (const invalidUuid of invalidUuids) {
expect(createValidator().validate(invalidUuid as string)).toBeFalsy()
}
})
})

View File

@@ -1,10 +0,0 @@
import { Uuid } from '../DataType/Uuid'
import { ValidatorInterface } from './ValidatorInterface'
export class UuidValidator implements ValidatorInterface<Uuid> {
private readonly UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i
validate(data: Uuid): boolean {
return String(data).toLowerCase().match(this.UUID_REGEX) !== null
}
}

View File

@@ -1,3 +0,0 @@
export interface ValidatorInterface<T> {
validate(data: T): boolean
}

View File

@@ -4,7 +4,6 @@ export * from './Content/ContentDecoderInterface'
export * from './DataType/AnyRecord'
export * from './DataType/JSONString'
export * from './DataType/MicrosecondsTimestamp'
export * from './DataType/Uuid'
export * from './DataType/ApplicationIdentifier'
export * from './Email/EmailMessageIdentifier'
export * from './Error/ErrorTag'
@@ -17,15 +16,11 @@ export * from './KeyParams/KeyParamsContent004'
export * from './KeyParams/KeyParamsOrigination'
export * from './Payment/PaymentType'
export * from './Protocol/ProtocolVersion'
export * from './Role/PaidRoles'
export * from './Role/RoleName'
export * from './Subscription/SubscriptionBillingFrequency'
export * from './Subscription/SubscriptionName'
export * from './Type/Either'
export * from './Type/Only'
export * from './User/UserRequestType'
export * from './Validator/UuidValidator'
export * from './Validator/ValidatorInterface'
export * from './Workspace/WorkspaceAccessLevel'
export * from './Workspace/WorkspaceType'
export * from './Workspace/WorkspaceUserStatus'

View File

@@ -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.9.65](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.64...@standardnotes/domain-events-infra@1.9.65) (2023-01-19)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.64](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.63...@standardnotes/domain-events-infra@1.9.64) (2023-01-19)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.63](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.62...@standardnotes/domain-events-infra@1.9.63) (2023-01-19)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.62](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.61...@standardnotes/domain-events-infra@1.9.62) (2023-01-19)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.61](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.60...@standardnotes/domain-events-infra@1.9.61) (2023-01-18)
**Note:** Version bump only for package @standardnotes/domain-events-infra

Some files were not shown because too many files have changed in this diff Show More