mirror of
https://github.com/standardnotes/server
synced 2026-05-10 00:57:19 -04:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d006ece30 | |||
| 037c994040 | |||
| a164ba291d | |||
| 610fba2601 | |||
| 398338c8f8 | |||
| 34be157d8e | |||
| 76372fe357 | |||
| 46879c336b | |||
| aef9e936bd | |||
| 8cb92d9678 | |||
| 52db89de81 | |||
| c5af8dfc05 | |||
| 27ad8e6959 | |||
| c4a1502f70 | |||
| d1d6c753c4 | |||
| 3bd63f7674 | |||
| 376466d9b2 | |||
| e100c52bbc | |||
| d4830dec01 | |||
| 7e11821021 |
@@ -21,7 +21,7 @@ jobs:
|
|||||||
e2e:
|
e2e:
|
||||||
name: (Self Hosting) E2E Test Suite
|
name: (Self Hosting) E2E Test Suite
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: true
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
secondary_db_enabled: [true, false]
|
secondary_db_enabled: [true, false]
|
||||||
transition_mode_enabled: [true, false]
|
transition_mode_enabled: [true, false]
|
||||||
@@ -70,7 +70,7 @@ jobs:
|
|||||||
e2e-home-server:
|
e2e-home-server:
|
||||||
name: (Home Server) E2E Test Suite
|
name: (Home Server) E2E Test Suite
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: true
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
db_type: [mysql, sqlite]
|
db_type: [mysql, sqlite]
|
||||||
cache_type: [redis, memory]
|
cache_type: [redis, memory]
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
name: E2E Test Suite On Self Hosted Server
|
name: E2E Test Suite On Self Hosted Server
|
||||||
|
|
||||||
|
run-name: E2E Test Suite against ${{ inputs.ref_name }} by ${{ inputs.author }}
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 */12 * * *'
|
- cron: '0 */12 * * *'
|
||||||
@@ -9,6 +11,14 @@ on:
|
|||||||
type: string
|
type: string
|
||||||
default: latest
|
default: latest
|
||||||
description: The Docker image tag used for SNJS container
|
description: The Docker image tag used for SNJS container
|
||||||
|
author:
|
||||||
|
type: string
|
||||||
|
default: unknown
|
||||||
|
description: The author that triggered the workflow
|
||||||
|
ref_name:
|
||||||
|
type: string
|
||||||
|
default: unknown
|
||||||
|
description: The ref name from which the workflow was triggered
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
e2e:
|
e2e:
|
||||||
|
|||||||
@@ -3,6 +3,18 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [2.26.7](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.26.6...@standardnotes/analytics@2.26.7) (2023-09-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.26.6](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.26.5...@standardnotes/analytics@2.26.6) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.26.5](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.26.4...@standardnotes/analytics@2.26.5) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
## [2.26.4](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.26.3...@standardnotes/analytics@2.26.4) (2023-09-06)
|
## [2.26.4](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.26.3...@standardnotes/analytics@2.26.4) (2023-09-06)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/analytics
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/analytics",
|
"name": "@standardnotes/analytics",
|
||||||
"version": "2.26.4",
|
"version": "2.26.7",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,18 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.74.3](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.74.2...@standardnotes/api-gateway@1.74.3) (2023-09-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.74.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.74.1...@standardnotes/api-gateway@1.74.2) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.74.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.74.0...@standardnotes/api-gateway@1.74.1) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
# [1.74.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.73.7...@standardnotes/api-gateway@1.74.0) (2023-09-06)
|
# [1.74.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.73.7...@standardnotes/api-gateway@1.74.0) (2023-09-06)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/api-gateway",
|
"name": "@standardnotes/api-gateway",
|
||||||
"version": "1.74.0",
|
"version": "1.74.3",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,31 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [1.140.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.139.0...@standardnotes/auth-server@1.140.0) (2023-09-08)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **auth:** specs ([a164ba2](https://github.com/standardnotes/server/commit/a164ba291d4893b5a0bb4b39a8795d654212a1a6))
|
||||||
|
* **auth:** transition users only when transition mode enabled ([610fba2](https://github.com/standardnotes/server/commit/610fba260150d0757020e01ac0c8967feeadd4d6))
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* transition users after sign out ([398338c](https://github.com/standardnotes/server/commit/398338c8f81b12406c7ab3bf1654e60b94d7cfd0))
|
||||||
|
|
||||||
|
# [1.139.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.138.2...@standardnotes/auth-server@1.139.0) (2023-09-08)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **auth:** add vaults user role into database ([aef9e93](https://github.com/standardnotes/server/commit/aef9e936bdbd1f4ccc32658d3d892e7675ec0e0e))
|
||||||
|
|
||||||
|
## [1.138.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.138.1...@standardnotes/auth-server@1.138.2) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
## [1.138.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.138.0...@standardnotes/auth-server@1.138.1) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
# [1.138.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.137.6...@standardnotes/auth-server@1.138.0) (2023-09-06)
|
# [1.138.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.137.6...@standardnotes/auth-server@1.138.0) (2023-09-06)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||||
|
|
||||||
|
export class AddVaultsUser1694157482134 implements MigrationInterface {
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
'INSERT INTO `roles` (uuid, name, version) VALUES ("35669f45-a2d8-4172-bdab-b7b3d42044ce", "VAULTS_USER", 1)',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(): Promise<void> {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/auth-server",
|
"name": "@standardnotes/auth-server",
|
||||||
"version": "1.138.0",
|
"version": "1.140.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -981,6 +981,7 @@ export class ContainerConfigLoader {
|
|||||||
container.get(TYPES.Auth_GenerateRecoveryCodes),
|
container.get(TYPES.Auth_GenerateRecoveryCodes),
|
||||||
container.get(TYPES.Auth_Logger),
|
container.get(TYPES.Auth_Logger),
|
||||||
container.get(TYPES.Auth_SessionService),
|
container.get(TYPES.Auth_SessionService),
|
||||||
|
container.get(TYPES.Auth_TRANSITION_MODE_ENABLED),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
container
|
container
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ describe('AuthController', () => {
|
|||||||
let doGenerateRecoveryCodes: GenerateRecoveryCodes
|
let doGenerateRecoveryCodes: GenerateRecoveryCodes
|
||||||
let logger: Logger
|
let logger: Logger
|
||||||
let sessionService: SessionServiceInterface
|
let sessionService: SessionServiceInterface
|
||||||
|
let transitionModeEnabled: boolean
|
||||||
|
|
||||||
const createController = () =>
|
const createController = () =>
|
||||||
new AuthController(
|
new AuthController(
|
||||||
@@ -39,6 +40,7 @@ describe('AuthController', () => {
|
|||||||
doGenerateRecoveryCodes,
|
doGenerateRecoveryCodes,
|
||||||
logger,
|
logger,
|
||||||
sessionService,
|
sessionService,
|
||||||
|
transitionModeEnabled,
|
||||||
)
|
)
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -64,6 +66,8 @@ describe('AuthController', () => {
|
|||||||
|
|
||||||
sessionService = {} as jest.Mocked<SessionServiceInterface>
|
sessionService = {} as jest.Mocked<SessionServiceInterface>
|
||||||
sessionService.deleteSessionByToken = jest.fn().mockReturnValue('1-2-3')
|
sessionService.deleteSessionByToken = jest.fn().mockReturnValue('1-2-3')
|
||||||
|
|
||||||
|
transitionModeEnabled = false
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should register a user', async () => {
|
it('should register a user', async () => {
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ export class AuthController implements UserServerInterface {
|
|||||||
private doGenerateRecoveryCodes: GenerateRecoveryCodes,
|
private doGenerateRecoveryCodes: GenerateRecoveryCodes,
|
||||||
private logger: Logger,
|
private logger: Logger,
|
||||||
private sessionService: SessionServiceInterface,
|
private sessionService: SessionServiceInterface,
|
||||||
|
private transitionModeEnabled: boolean,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async update(_params: UserUpdateRequestParams): Promise<HttpResponse<UserUpdateResponse>> {
|
async update(_params: UserUpdateRequestParams): Promise<HttpResponse<UserUpdateResponse>> {
|
||||||
@@ -226,6 +227,14 @@ export class AuthController implements UserServerInterface {
|
|||||||
let headers = undefined
|
let headers = undefined
|
||||||
if (userUuid !== null) {
|
if (userUuid !== null) {
|
||||||
headers = new Map([['x-invalidate-cache', userUuid]])
|
headers = new Map([['x-invalidate-cache', userUuid]])
|
||||||
|
|
||||||
|
if (this.transitionModeEnabled) {
|
||||||
|
await this.domainEventPublisher.publish(
|
||||||
|
this.domainEventFactory.createTransitionRequestedEvent({
|
||||||
|
userUuid,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import {
|
|||||||
StatisticPersistenceRequestedEvent,
|
StatisticPersistenceRequestedEvent,
|
||||||
SessionCreatedEvent,
|
SessionCreatedEvent,
|
||||||
SessionRefreshedEvent,
|
SessionRefreshedEvent,
|
||||||
|
TransitionRequestedEvent,
|
||||||
} from '@standardnotes/domain-events'
|
} from '@standardnotes/domain-events'
|
||||||
import { Predicate, PredicateVerificationResult } from '@standardnotes/predicates'
|
import { Predicate, PredicateVerificationResult } from '@standardnotes/predicates'
|
||||||
import { TimerInterface } from '@standardnotes/time'
|
import { TimerInterface } from '@standardnotes/time'
|
||||||
@@ -32,6 +33,21 @@ import { DomainEventFactoryInterface } from './DomainEventFactoryInterface'
|
|||||||
export class DomainEventFactory implements DomainEventFactoryInterface {
|
export class DomainEventFactory implements DomainEventFactoryInterface {
|
||||||
constructor(@inject(TYPES.Auth_Timer) private timer: TimerInterface) {}
|
constructor(@inject(TYPES.Auth_Timer) private timer: TimerInterface) {}
|
||||||
|
|
||||||
|
createTransitionRequestedEvent(dto: { userUuid: string }): 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 {
|
createSessionCreatedEvent(dto: { userUuid: string }): SessionCreatedEvent {
|
||||||
return {
|
return {
|
||||||
type: 'SESSION_CREATED',
|
type: 'SESSION_CREATED',
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
StatisticPersistenceRequestedEvent,
|
StatisticPersistenceRequestedEvent,
|
||||||
SessionCreatedEvent,
|
SessionCreatedEvent,
|
||||||
SessionRefreshedEvent,
|
SessionRefreshedEvent,
|
||||||
|
TransitionRequestedEvent,
|
||||||
} from '@standardnotes/domain-events'
|
} from '@standardnotes/domain-events'
|
||||||
import { InviteeIdentifierType } from '../SharedSubscription/InviteeIdentifierType'
|
import { InviteeIdentifierType } from '../SharedSubscription/InviteeIdentifierType'
|
||||||
|
|
||||||
@@ -89,4 +90,5 @@ export interface DomainEventFactoryInterface {
|
|||||||
}): StatisticPersistenceRequestedEvent
|
}): StatisticPersistenceRequestedEvent
|
||||||
createSessionCreatedEvent(dto: { userUuid: string }): SessionCreatedEvent
|
createSessionCreatedEvent(dto: { userUuid: string }): SessionCreatedEvent
|
||||||
createSessionRefreshedEvent(dto: { userUuid: string }): SessionRefreshedEvent
|
createSessionRefreshedEvent(dto: { userUuid: string }): SessionRefreshedEvent
|
||||||
|
createTransitionRequestedEvent(dto: { userUuid: string }): TransitionRequestedEvent
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [1.28.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.27.0...@standardnotes/domain-core@1.28.0) (2023-09-07)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add VaultsUser role name ([#809](https://github.com/standardnotes/server/issues/809)) ([d4830de](https://github.com/standardnotes/server/commit/d4830dec018139ffaf93d0e91d6655c5dcc6be9c))
|
||||||
|
|
||||||
# [1.27.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.26.3...@standardnotes/domain-core@1.27.0) (2023-09-06)
|
# [1.27.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.26.3...@standardnotes/domain-core@1.27.0) (2023-09-06)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/domain-core",
|
"name": "@standardnotes/domain-core",
|
||||||
"version": "1.27.0",
|
"version": "1.28.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export class RoleName extends ValueObject<RoleNameProps> {
|
|||||||
ProUser: 'PRO_USER',
|
ProUser: 'PRO_USER',
|
||||||
InternalTeamUser: 'INTERNAL_TEAM_USER',
|
InternalTeamUser: 'INTERNAL_TEAM_USER',
|
||||||
TransitionUser: 'TRANSITION_USER',
|
TransitionUser: 'TRANSITION_USER',
|
||||||
|
VaultsUser: 'VAULTS_USER',
|
||||||
}
|
}
|
||||||
|
|
||||||
get value(): string {
|
get value(): string {
|
||||||
@@ -32,6 +33,7 @@ export class RoleName extends ValueObject<RoleNameProps> {
|
|||||||
)
|
)
|
||||||
case RoleName.NAMES.CoreUser:
|
case RoleName.NAMES.CoreUser:
|
||||||
case RoleName.NAMES.TransitionUser:
|
case RoleName.NAMES.TransitionUser:
|
||||||
|
case RoleName.NAMES.VaultsUser:
|
||||||
return [RoleName.NAMES.CoreUser, RoleName.NAMES.TransitionUser].includes(roleName.value)
|
return [RoleName.NAMES.CoreUser, RoleName.NAMES.TransitionUser].includes(roleName.value)
|
||||||
/*istanbul ignore next*/
|
/*istanbul ignore next*/
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ describe('RoleNameCollection', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should tell if collection has a role with more or equal power to', () => {
|
it('should tell if collection has a role with more or equal power to', () => {
|
||||||
let roles = [RoleName.NAMES.CoreUser]
|
let roles = [RoleName.NAMES.VaultsUser]
|
||||||
let valueOrError = RoleNameCollection.create(roles)
|
let valueOrError = RoleNameCollection.create(roles)
|
||||||
let roleNames = valueOrError.getValue()
|
let roleNames = valueOrError.getValue()
|
||||||
|
|
||||||
@@ -63,6 +63,18 @@ describe('RoleNameCollection', () => {
|
|||||||
roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.CoreUser).getValue()),
|
roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.CoreUser).getValue()),
|
||||||
).toBeTruthy()
|
).toBeTruthy()
|
||||||
|
|
||||||
|
roles = [RoleName.NAMES.CoreUser]
|
||||||
|
valueOrError = RoleNameCollection.create(roles)
|
||||||
|
roleNames = valueOrError.getValue()
|
||||||
|
|
||||||
|
expect(
|
||||||
|
roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.PlusUser).getValue()),
|
||||||
|
).toBeFalsy()
|
||||||
|
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.ProUser).getValue())).toBeFalsy()
|
||||||
|
expect(
|
||||||
|
roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.CoreUser).getValue()),
|
||||||
|
).toBeTruthy()
|
||||||
|
|
||||||
roles = [RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser]
|
roles = [RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser]
|
||||||
valueOrError = RoleNameCollection.create(roles)
|
valueOrError = RoleNameCollection.create(roles)
|
||||||
roleNames = valueOrError.getValue()
|
roleNames = valueOrError.getValue()
|
||||||
|
|||||||
@@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.12.24](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.12.23...@standardnotes/domain-events-infra@1.12.24) (2023-09-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||||
|
|
||||||
|
## [1.12.23](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.12.22...@standardnotes/domain-events-infra@1.12.23) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||||
|
|
||||||
## [1.12.22](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.12.21...@standardnotes/domain-events-infra@1.12.22) (2023-09-06)
|
## [1.12.22](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.12.21...@standardnotes/domain-events-infra@1.12.22) (2023-09-06)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/domain-events-infra",
|
"name": "@standardnotes/domain-events-infra",
|
||||||
"version": "1.12.22",
|
"version": "1.12.24",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,18 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [2.125.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.124.0...@standardnotes/domain-events@2.125.0) (2023-09-08)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* transition users after sign out ([398338c](https://github.com/standardnotes/server/commit/398338c8f81b12406c7ab3bf1654e60b94d7cfd0))
|
||||||
|
|
||||||
|
# [2.124.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.123.0...@standardnotes/domain-events@2.124.0) (2023-09-07)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add removing revisions from shared vaults ([#811](https://github.com/standardnotes/server/issues/811)) ([3bd63f7](https://github.com/standardnotes/server/commit/3bd63f767464baf9b9f1ffa52eea9eed4a4e11b5))
|
||||||
|
|
||||||
# [2.123.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.122.2...@standardnotes/domain-events@2.123.0) (2023-09-06)
|
# [2.123.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.122.2...@standardnotes/domain-events@2.123.0) (2023-09-06)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/domain-events",
|
"name": "@standardnotes/domain-events",
|
||||||
"version": "2.123.0",
|
"version": "2.125.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { DomainEventInterface } from './DomainEventInterface'
|
||||||
|
import { ItemRemovedFromSharedVaultEventPayload } from './ItemRemovedFromSharedVaultEventPayload'
|
||||||
|
|
||||||
|
export interface ItemRemovedFromSharedVaultEvent extends DomainEventInterface {
|
||||||
|
type: 'ITEM_REMOVED_FROM_SHARED_VAULT'
|
||||||
|
payload: ItemRemovedFromSharedVaultEventPayload
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
export interface ItemRemovedFromSharedVaultEventPayload {
|
||||||
|
userUuid: string
|
||||||
|
itemUuid: string
|
||||||
|
sharedVaultUuid: string
|
||||||
|
roleNames: string[]
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { DomainEventInterface } from './DomainEventInterface'
|
||||||
|
|
||||||
|
import { TransitionRequestedEventPayload } from './TransitionRequestedEventPayload'
|
||||||
|
|
||||||
|
export interface TransitionRequestedEvent extends DomainEventInterface {
|
||||||
|
type: 'TRANSITION_REQUESTED'
|
||||||
|
payload: TransitionRequestedEventPayload
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export interface TransitionRequestedEventPayload {
|
||||||
|
userUuid: string
|
||||||
|
}
|
||||||
@@ -32,6 +32,8 @@ export * from './Event/FileUploadedEvent'
|
|||||||
export * from './Event/FileUploadedEventPayload'
|
export * from './Event/FileUploadedEventPayload'
|
||||||
export * from './Event/ItemDumpedEvent'
|
export * from './Event/ItemDumpedEvent'
|
||||||
export * from './Event/ItemDumpedEventPayload'
|
export * from './Event/ItemDumpedEventPayload'
|
||||||
|
export * from './Event/ItemRemovedFromSharedVaultEvent'
|
||||||
|
export * from './Event/ItemRemovedFromSharedVaultEventPayload'
|
||||||
export * from './Event/ItemRevisionCreationRequestedEvent'
|
export * from './Event/ItemRevisionCreationRequestedEvent'
|
||||||
export * from './Event/ItemRevisionCreationRequestedEventPayload'
|
export * from './Event/ItemRevisionCreationRequestedEventPayload'
|
||||||
export * from './Event/ListedAccountCreatedEvent'
|
export * from './Event/ListedAccountCreatedEvent'
|
||||||
@@ -94,6 +96,8 @@ export * from './Event/SubscriptionRevertRequestedEvent'
|
|||||||
export * from './Event/SubscriptionRevertRequestedEventPayload'
|
export * from './Event/SubscriptionRevertRequestedEventPayload'
|
||||||
export * from './Event/SubscriptionSyncRequestedEvent'
|
export * from './Event/SubscriptionSyncRequestedEvent'
|
||||||
export * from './Event/SubscriptionSyncRequestedEventPayload'
|
export * from './Event/SubscriptionSyncRequestedEventPayload'
|
||||||
|
export * from './Event/TransitionRequestedEvent'
|
||||||
|
export * from './Event/TransitionRequestedEventPayload'
|
||||||
export * from './Event/TransitionStatusUpdatedEvent'
|
export * from './Event/TransitionStatusUpdatedEvent'
|
||||||
export * from './Event/TransitionStatusUpdatedEventPayload'
|
export * from './Event/TransitionStatusUpdatedEventPayload'
|
||||||
export * from './Event/UserAddedToSharedVaultEvent'
|
export * from './Event/UserAddedToSharedVaultEvent'
|
||||||
|
|||||||
@@ -3,6 +3,18 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.11.35](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.34...@standardnotes/event-store@1.11.35) (2023-09-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.11.34](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.33...@standardnotes/event-store@1.11.34) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.11.33](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.32...@standardnotes/event-store@1.11.33) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
## [1.11.32](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.31...@standardnotes/event-store@1.11.32) (2023-09-06)
|
## [1.11.32](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.31...@standardnotes/event-store@1.11.32) (2023-09-06)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/event-store
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/event-store",
|
"name": "@standardnotes/event-store",
|
||||||
"version": "1.11.32",
|
"version": "1.11.35",
|
||||||
"description": "Event Store Service",
|
"description": "Event Store Service",
|
||||||
"private": true,
|
"private": true,
|
||||||
"main": "dist/src/index.js",
|
"main": "dist/src/index.js",
|
||||||
|
|||||||
@@ -3,6 +3,18 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.22.14](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.22.13...@standardnotes/files-server@1.22.14) (2023-09-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
## [1.22.13](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.22.12...@standardnotes/files-server@1.22.13) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
## [1.22.12](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.22.11...@standardnotes/files-server@1.22.12) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
## [1.22.11](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.22.10...@standardnotes/files-server@1.22.11) (2023-09-06)
|
## [1.22.11](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.22.10...@standardnotes/files-server@1.22.11) (2023-09-06)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/files-server
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/files-server",
|
"name": "@standardnotes/files-server",
|
||||||
"version": "1.22.11",
|
"version": "1.22.14",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,30 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.15.31](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.15.30...@standardnotes/home-server@1.15.31) (2023-09-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.15.30](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.15.29...@standardnotes/home-server@1.15.30) (2023-09-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.15.29](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.15.28...@standardnotes/home-server@1.15.29) (2023-09-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.15.28](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.15.27...@standardnotes/home-server@1.15.28) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.15.27](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.15.26...@standardnotes/home-server@1.15.27) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
|
## [1.15.26](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.15.25...@standardnotes/home-server@1.15.26) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|
||||||
## [1.15.25](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.15.24...@standardnotes/home-server@1.15.25) (2023-09-06)
|
## [1.15.25](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.15.24...@standardnotes/home-server@1.15.25) (2023-09-06)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/home-server
|
**Note:** Version bump only for package @standardnotes/home-server
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/home-server",
|
"name": "@standardnotes/home-server",
|
||||||
"version": "1.15.25",
|
"version": "1.15.31",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,38 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.33.3](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.33.2...@standardnotes/revisions-server@1.33.3) (2023-09-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||||
|
|
||||||
|
## [1.33.2](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.33.1...@standardnotes/revisions-server@1.33.2) (2023-09-08)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **revisions:** persistence mapper ([#814](https://github.com/standardnotes/server/issues/814)) ([76372fe](https://github.com/standardnotes/server/commit/76372fe3579a99bf44abfce9667fec134baafedf))
|
||||||
|
|
||||||
|
## [1.33.1](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.33.0...@standardnotes/revisions-server@1.33.1) (2023-09-07)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **revisions:** waiting for syncing-server on self-hosted setup ([27ad8e6](https://github.com/standardnotes/server/commit/27ad8e6959aeb9c2f11ee0fecba37514bf91dda8))
|
||||||
|
|
||||||
|
# [1.33.0](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.32.0...@standardnotes/revisions-server@1.33.0) (2023-09-07)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add removing revisions from shared vaults ([#811](https://github.com/standardnotes/server/issues/811)) ([3bd63f7](https://github.com/standardnotes/server/commit/3bd63f767464baf9b9f1ffa52eea9eed4a4e11b5))
|
||||||
|
|
||||||
|
# [1.32.0](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.31.0...@standardnotes/revisions-server@1.32.0) (2023-09-07)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **revisions:** query for shared vault revisions ([7e11821](https://github.com/standardnotes/server/commit/7e11821021a663fcf452ad8bb03eda33c03fe221))
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **revisions:** fetching single revision in shared vault ([#810](https://github.com/standardnotes/server/issues/810)) ([e100c52](https://github.com/standardnotes/server/commit/e100c52bbc07447188af3b9a04f3744401dac0ab))
|
||||||
|
|
||||||
# [1.31.0](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.30.14...@standardnotes/revisions-server@1.31.0) (2023-09-06)
|
# [1.31.0](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.30.14...@standardnotes/revisions-server@1.31.0) (2023-09-06)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/revisions-server",
|
"name": "@standardnotes/revisions-server",
|
||||||
"version": "1.31.0",
|
"version": "1.33.3",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ import { SQLRevision } from '../Infra/TypeORM/SQL/SQLRevision'
|
|||||||
import { SQLRevisionRepository } from '../Infra/TypeORM/SQL/SQLRevisionRepository'
|
import { SQLRevisionRepository } from '../Infra/TypeORM/SQL/SQLRevisionRepository'
|
||||||
import { SQLRevisionMetadataPersistenceMapper } from '../Mapping/Persistence/SQL/SQLRevisionMetadataPersistenceMapper'
|
import { SQLRevisionMetadataPersistenceMapper } from '../Mapping/Persistence/SQL/SQLRevisionMetadataPersistenceMapper'
|
||||||
import { SQLRevisionPersistenceMapper } from '../Mapping/Persistence/SQL/SQLRevisionPersistenceMapper'
|
import { SQLRevisionPersistenceMapper } from '../Mapping/Persistence/SQL/SQLRevisionPersistenceMapper'
|
||||||
|
import { RemoveRevisionsFromSharedVault } from '../Domain/UseCase/RemoveRevisionsFromSharedVault/RemoveRevisionsFromSharedVault'
|
||||||
|
import { ItemRemovedFromSharedVaultEventHandler } from '../Domain/Handler/ItemRemovedFromSharedVaultEventHandler'
|
||||||
|
|
||||||
export class ContainerConfigLoader {
|
export class ContainerConfigLoader {
|
||||||
async load(configuration?: {
|
async load(configuration?: {
|
||||||
@@ -358,6 +360,13 @@ export class ContainerConfigLoader {
|
|||||||
container.get<DomainEventFactoryInterface>(TYPES.Revisions_DomainEventFactory),
|
container.get<DomainEventFactoryInterface>(TYPES.Revisions_DomainEventFactory),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
container
|
||||||
|
.bind<RemoveRevisionsFromSharedVault>(TYPES.Revisions_RemoveRevisionsFromSharedVault)
|
||||||
|
.toConstantValue(
|
||||||
|
new RemoveRevisionsFromSharedVault(
|
||||||
|
container.get<RevisionRepositoryResolverInterface>(TYPES.Revisions_RevisionRepositoryResolver),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
// env vars
|
// env vars
|
||||||
container.bind(TYPES.Revisions_AUTH_JWT_SECRET).toConstantValue(env.get('AUTH_JWT_SECRET'))
|
container.bind(TYPES.Revisions_AUTH_JWT_SECRET).toConstantValue(env.get('AUTH_JWT_SECRET'))
|
||||||
@@ -437,12 +446,21 @@ export class ContainerConfigLoader {
|
|||||||
container.get<winston.Logger>(TYPES.Revisions_Logger),
|
container.get<winston.Logger>(TYPES.Revisions_Logger),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
container
|
||||||
|
.bind<ItemRemovedFromSharedVaultEventHandler>(TYPES.Revisions_ItemRemovedFromSharedVaultEventHandler)
|
||||||
|
.toConstantValue(
|
||||||
|
new ItemRemovedFromSharedVaultEventHandler(
|
||||||
|
container.get<RemoveRevisionsFromSharedVault>(TYPES.Revisions_RemoveRevisionsFromSharedVault),
|
||||||
|
container.get<winston.Logger>(TYPES.Revisions_Logger),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
|
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
|
||||||
['ITEM_DUMPED', container.get(TYPES.Revisions_ItemDumpedEventHandler)],
|
['ITEM_DUMPED', container.get(TYPES.Revisions_ItemDumpedEventHandler)],
|
||||||
['ACCOUNT_DELETION_REQUESTED', container.get(TYPES.Revisions_AccountDeletionRequestedEventHandler)],
|
['ACCOUNT_DELETION_REQUESTED', container.get(TYPES.Revisions_AccountDeletionRequestedEventHandler)],
|
||||||
['REVISIONS_COPY_REQUESTED', container.get(TYPES.Revisions_RevisionsCopyRequestedEventHandler)],
|
['REVISIONS_COPY_REQUESTED', container.get(TYPES.Revisions_RevisionsCopyRequestedEventHandler)],
|
||||||
['TRANSITION_STATUS_UPDATED', container.get(TYPES.Revisions_TransitionStatusUpdatedEventHandler)],
|
['TRANSITION_STATUS_UPDATED', container.get(TYPES.Revisions_TransitionStatusUpdatedEventHandler)],
|
||||||
|
['ITEM_REMOVED_FROM_SHARED_VAULT', container.get(TYPES.Revisions_ItemRemovedFromSharedVaultEventHandler)],
|
||||||
])
|
])
|
||||||
|
|
||||||
if (isConfiguredForHomeServer) {
|
if (isConfiguredForHomeServer) {
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ const TYPES = {
|
|||||||
Revisions_TriggerTransitionFromPrimaryToSecondaryDatabaseForUser: Symbol.for(
|
Revisions_TriggerTransitionFromPrimaryToSecondaryDatabaseForUser: Symbol.for(
|
||||||
'Revisions_TriggerTransitionFromPrimaryToSecondaryDatabaseForUser',
|
'Revisions_TriggerTransitionFromPrimaryToSecondaryDatabaseForUser',
|
||||||
),
|
),
|
||||||
|
Revisions_RemoveRevisionsFromSharedVault: Symbol.for('Revisions_RemoveRevisionsFromSharedVault'),
|
||||||
// Controller
|
// Controller
|
||||||
Revisions_ControllerContainer: Symbol.for('Revisions_ControllerContainer'),
|
Revisions_ControllerContainer: Symbol.for('Revisions_ControllerContainer'),
|
||||||
Revisions_RevisionsController: Symbol.for('Revisions_RevisionsController'),
|
Revisions_RevisionsController: Symbol.for('Revisions_RevisionsController'),
|
||||||
@@ -58,6 +59,7 @@ const TYPES = {
|
|||||||
Revisions_AccountDeletionRequestedEventHandler: Symbol.for('Revisions_AccountDeletionRequestedEventHandler'),
|
Revisions_AccountDeletionRequestedEventHandler: Symbol.for('Revisions_AccountDeletionRequestedEventHandler'),
|
||||||
Revisions_RevisionsCopyRequestedEventHandler: Symbol.for('Revisions_RevisionsCopyRequestedEventHandler'),
|
Revisions_RevisionsCopyRequestedEventHandler: Symbol.for('Revisions_RevisionsCopyRequestedEventHandler'),
|
||||||
Revisions_TransitionStatusUpdatedEventHandler: Symbol.for('Revisions_TransitionStatusUpdatedEventHandler'),
|
Revisions_TransitionStatusUpdatedEventHandler: Symbol.for('Revisions_TransitionStatusUpdatedEventHandler'),
|
||||||
|
Revisions_ItemRemovedFromSharedVaultEventHandler: Symbol.for('Revisions_ItemRemovedFromSharedVaultEventHandler'),
|
||||||
// Services
|
// Services
|
||||||
Revisions_CrossServiceTokenDecoder: Symbol.for('Revisions_CrossServiceTokenDecoder'),
|
Revisions_CrossServiceTokenDecoder: Symbol.for('Revisions_CrossServiceTokenDecoder'),
|
||||||
Revisions_DomainEventSubscriberFactory: Symbol.for('Revisions_DomainEventSubscriberFactory'),
|
Revisions_DomainEventSubscriberFactory: Symbol.for('Revisions_DomainEventSubscriberFactory'),
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { DomainEventHandlerInterface, ItemRemovedFromSharedVaultEvent } from '@standardnotes/domain-events'
|
||||||
|
import { RemoveRevisionsFromSharedVault } from '../UseCase/RemoveRevisionsFromSharedVault/RemoveRevisionsFromSharedVault'
|
||||||
|
import { Logger } from 'winston'
|
||||||
|
|
||||||
|
export class ItemRemovedFromSharedVaultEventHandler implements DomainEventHandlerInterface {
|
||||||
|
constructor(
|
||||||
|
private removeRevisionsFromSharedVault: RemoveRevisionsFromSharedVault,
|
||||||
|
private logger: Logger,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async handle(event: ItemRemovedFromSharedVaultEvent): Promise<void> {
|
||||||
|
const result = await this.removeRevisionsFromSharedVault.execute({
|
||||||
|
sharedVaultUuid: event.payload.sharedVaultUuid,
|
||||||
|
itemUuid: event.payload.itemUuid,
|
||||||
|
roleNames: event.payload.roleNames,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (result.isFailed()) {
|
||||||
|
this.logger.error(`Failed to remove revisions from shared vault: ${result.getError()}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,10 +7,11 @@ export interface RevisionRepositoryInterface {
|
|||||||
countByUserUuid(userUuid: Uuid): Promise<number>
|
countByUserUuid(userUuid: Uuid): Promise<number>
|
||||||
removeByUserUuid(userUuid: Uuid): Promise<void>
|
removeByUserUuid(userUuid: Uuid): Promise<void>
|
||||||
removeOneByUuid(revisionUuid: Uuid, userUuid: Uuid): Promise<void>
|
removeOneByUuid(revisionUuid: Uuid, userUuid: Uuid): Promise<void>
|
||||||
findOneByUuid(revisionUuid: Uuid, userUuid: Uuid): Promise<Revision | null>
|
findOneByUuid(revisionUuid: Uuid, userUuid: Uuid, sharedVaultUuids: Uuid[]): Promise<Revision | null>
|
||||||
findByItemUuid(itemUuid: Uuid): Promise<Array<Revision>>
|
findByItemUuid(itemUuid: Uuid): Promise<Array<Revision>>
|
||||||
findMetadataByItemId(itemUuid: Uuid, userUuid: Uuid, sharedVaultUuids: Uuid[]): Promise<Array<RevisionMetadata>>
|
findMetadataByItemId(itemUuid: Uuid, userUuid: Uuid, sharedVaultUuids: Uuid[]): Promise<Array<RevisionMetadata>>
|
||||||
updateUserUuid(itemUuid: Uuid, userUuid: Uuid): Promise<void>
|
updateUserUuid(itemUuid: Uuid, userUuid: Uuid): Promise<void>
|
||||||
findByUserUuid(dto: { userUuid: Uuid; offset?: number; limit?: number }): Promise<Array<Revision>>
|
findByUserUuid(dto: { userUuid: Uuid; offset?: number; limit?: number }): Promise<Array<Revision>>
|
||||||
insert(revision: Revision): Promise<boolean>
|
insert(revision: Revision): Promise<boolean>
|
||||||
|
clearSharedVaultAndKeySystemAssociations(itemUuid: Uuid, sharedVaultUuid: Uuid): Promise<void>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,17 +22,30 @@ describe('GetRevision', () => {
|
|||||||
revisionUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
revisionUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
||||||
userUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
userUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
||||||
roleNames: ['CORE_USER'],
|
roleNames: ['CORE_USER'],
|
||||||
|
sharedVaultUuids: ['84c0f8e8-544a-4c7e-9adf-26209303bc1d'],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result.isFailed()).toBeFalsy()
|
expect(result.isFailed()).toBeFalsy()
|
||||||
expect(result.getValue()).not.toBeNull()
|
expect(result.getValue()).not.toBeNull()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should do nothing if shared vault uuid is invalid', async () => {
|
||||||
|
const result = await createUseCase().execute({
|
||||||
|
revisionUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
||||||
|
userUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
||||||
|
roleNames: ['CORE_USER'],
|
||||||
|
sharedVaultUuids: ['INVALID_SHARED_VAULT_UUID'],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result.isFailed()).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
it('should do nothing if role names are not valid', async () => {
|
it('should do nothing if role names are not valid', async () => {
|
||||||
const result = await createUseCase().execute({
|
const result = await createUseCase().execute({
|
||||||
revisionUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
revisionUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
||||||
userUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
userUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
||||||
roleNames: ['INVALID_ROLE_NAME'],
|
roleNames: ['INVALID_ROLE_NAME'],
|
||||||
|
sharedVaultUuids: ['84c0f8e8-544a-4c7e-9adf-26209303bc1d'],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result.isFailed()).toBeTruthy()
|
expect(result.isFailed()).toBeTruthy()
|
||||||
@@ -45,6 +58,7 @@ describe('GetRevision', () => {
|
|||||||
revisionUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
revisionUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
||||||
userUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
userUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
||||||
roleNames: ['CORE_USER'],
|
roleNames: ['CORE_USER'],
|
||||||
|
sharedVaultUuids: ['84c0f8e8-544a-4c7e-9adf-26209303bc1d'],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result.isFailed()).toBeTruthy()
|
expect(result.isFailed()).toBeTruthy()
|
||||||
@@ -55,6 +69,7 @@ describe('GetRevision', () => {
|
|||||||
revisionUuid: '1-2-3',
|
revisionUuid: '1-2-3',
|
||||||
userUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
userUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
||||||
roleNames: ['CORE_USER'],
|
roleNames: ['CORE_USER'],
|
||||||
|
sharedVaultUuids: ['84c0f8e8-544a-4c7e-9adf-26209303bc1d'],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result.isFailed()).toBeTruthy()
|
expect(result.isFailed()).toBeTruthy()
|
||||||
@@ -65,6 +80,7 @@ describe('GetRevision', () => {
|
|||||||
userUuid: '1-2-3',
|
userUuid: '1-2-3',
|
||||||
revisionUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
revisionUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
||||||
roleNames: ['CORE_USER'],
|
roleNames: ['CORE_USER'],
|
||||||
|
sharedVaultUuids: ['84c0f8e8-544a-4c7e-9adf-26209303bc1d'],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result.isFailed()).toBeTruthy()
|
expect(result.isFailed()).toBeTruthy()
|
||||||
|
|||||||
@@ -26,9 +26,18 @@ export class GetRevision implements UseCaseInterface<Revision> {
|
|||||||
}
|
}
|
||||||
const roleNames = roleNamesOrError.getValue()
|
const roleNames = roleNamesOrError.getValue()
|
||||||
|
|
||||||
|
const sharedVaultUuids = []
|
||||||
|
for (const sharedVaultUuid of dto.sharedVaultUuids) {
|
||||||
|
const sharedVaultUuidOrError = Uuid.create(sharedVaultUuid)
|
||||||
|
if (sharedVaultUuidOrError.isFailed()) {
|
||||||
|
return Result.fail(`Could not get revision: ${sharedVaultUuidOrError.getError()}`)
|
||||||
|
}
|
||||||
|
sharedVaultUuids.push(sharedVaultUuidOrError.getValue())
|
||||||
|
}
|
||||||
|
|
||||||
const revisionRepository = this.revisionRepositoryResolver.resolve(roleNames)
|
const revisionRepository = this.revisionRepositoryResolver.resolve(roleNames)
|
||||||
|
|
||||||
const revision = await revisionRepository.findOneByUuid(revisionUuid, userUuid)
|
const revision = await revisionRepository.findOneByUuid(revisionUuid, userUuid, sharedVaultUuids)
|
||||||
|
|
||||||
if (revision === null) {
|
if (revision === null) {
|
||||||
return Result.fail<Revision>(`Could not find revision with uuid: ${revisionUuid.value}`)
|
return Result.fail<Revision>(`Could not find revision with uuid: ${revisionUuid.value}`)
|
||||||
|
|||||||
@@ -2,4 +2,5 @@ export interface GetRevisionDTO {
|
|||||||
userUuid: string
|
userUuid: string
|
||||||
revisionUuid: string
|
revisionUuid: string
|
||||||
roleNames: string[]
|
roleNames: string[]
|
||||||
|
sharedVaultUuids: string[]
|
||||||
}
|
}
|
||||||
|
|||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
import { RevisionRepositoryInterface } from '../../Revision/RevisionRepositoryInterface'
|
||||||
|
import { RevisionRepositoryResolverInterface } from '../../Revision/RevisionRepositoryResolverInterface'
|
||||||
|
import { RemoveRevisionsFromSharedVault } from './RemoveRevisionsFromSharedVault'
|
||||||
|
|
||||||
|
describe('RemoveRevisionsFromSharedVault', () => {
|
||||||
|
let revisionRepositoryResolver: RevisionRepositoryResolverInterface
|
||||||
|
let revisionRepository: RevisionRepositoryInterface
|
||||||
|
|
||||||
|
const createUseCase = () => new RemoveRevisionsFromSharedVault(revisionRepositoryResolver)
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
revisionRepository = {} as jest.Mocked<RevisionRepositoryInterface>
|
||||||
|
revisionRepository.clearSharedVaultAndKeySystemAssociations = jest.fn()
|
||||||
|
|
||||||
|
revisionRepositoryResolver = {} as jest.Mocked<RevisionRepositoryResolverInterface>
|
||||||
|
revisionRepositoryResolver.resolve = jest.fn().mockReturnValue(revisionRepository)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should clear shared vault and key system associations', async () => {
|
||||||
|
const useCase = createUseCase()
|
||||||
|
|
||||||
|
await useCase.execute({
|
||||||
|
itemUuid: '00000000-0000-0000-0000-000000000000',
|
||||||
|
sharedVaultUuid: '00000000-0000-0000-0000-000000000001',
|
||||||
|
roleNames: ['CORE_USER'],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(revisionRepository.clearSharedVaultAndKeySystemAssociations).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return error when shared vault uuid is invalid', async () => {
|
||||||
|
const useCase = createUseCase()
|
||||||
|
|
||||||
|
const result = await useCase.execute({
|
||||||
|
itemUuid: '00000000-0000-0000-0000-000000000000',
|
||||||
|
sharedVaultUuid: 'invalid',
|
||||||
|
roleNames: ['CORE_USER'],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result.isFailed()).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return error when item uuid is invalid', async () => {
|
||||||
|
const useCase = createUseCase()
|
||||||
|
|
||||||
|
const result = await useCase.execute({
|
||||||
|
itemUuid: 'invalid',
|
||||||
|
sharedVaultUuid: '00000000-0000-0000-0000-000000000001',
|
||||||
|
roleNames: ['CORE_USER'],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result.isFailed()).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return error when role names are invalid', async () => {
|
||||||
|
const useCase = createUseCase()
|
||||||
|
|
||||||
|
const result = await useCase.execute({
|
||||||
|
itemUuid: '00000000-0000-0000-0000-000000000000',
|
||||||
|
sharedVaultUuid: '00000000-0000-0000-0000-000000000001',
|
||||||
|
roleNames: ['invalid'],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result.isFailed()).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
import { Result, RoleNameCollection, UseCaseInterface, Uuid } from '@standardnotes/domain-core'
|
||||||
|
import { RevisionRepositoryResolverInterface } from '../../Revision/RevisionRepositoryResolverInterface'
|
||||||
|
import { RemoveRevisionsFromSharedVaultDTO } from './RemoveRevisionsFromSharedVaultDTO'
|
||||||
|
|
||||||
|
export class RemoveRevisionsFromSharedVault implements UseCaseInterface<void> {
|
||||||
|
constructor(private revisionRepositoryResolver: RevisionRepositoryResolverInterface) {}
|
||||||
|
|
||||||
|
async execute(dto: RemoveRevisionsFromSharedVaultDTO): Promise<Result<void>> {
|
||||||
|
const sharedVaultUuidOrError = Uuid.create(dto.sharedVaultUuid)
|
||||||
|
if (sharedVaultUuidOrError.isFailed()) {
|
||||||
|
return Result.fail(sharedVaultUuidOrError.getError())
|
||||||
|
}
|
||||||
|
const sharedVaultUuid = sharedVaultUuidOrError.getValue()
|
||||||
|
|
||||||
|
const itemUuidOrError = Uuid.create(dto.itemUuid)
|
||||||
|
if (itemUuidOrError.isFailed()) {
|
||||||
|
return Result.fail(itemUuidOrError.getError())
|
||||||
|
}
|
||||||
|
const itemUuid = itemUuidOrError.getValue()
|
||||||
|
|
||||||
|
const roleNamesOrError = RoleNameCollection.create(dto.roleNames)
|
||||||
|
if (roleNamesOrError.isFailed()) {
|
||||||
|
return Result.fail(roleNamesOrError.getError())
|
||||||
|
}
|
||||||
|
const roleNames = roleNamesOrError.getValue()
|
||||||
|
|
||||||
|
const revisionRepository = this.revisionRepositoryResolver.resolve(roleNames)
|
||||||
|
|
||||||
|
await revisionRepository.clearSharedVaultAndKeySystemAssociations(itemUuid, sharedVaultUuid)
|
||||||
|
|
||||||
|
return Result.ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
export interface RemoveRevisionsFromSharedVaultDTO {
|
||||||
|
itemUuid: string
|
||||||
|
sharedVaultUuid: string
|
||||||
|
roleNames: string[]
|
||||||
|
}
|
||||||
+1
-1
@@ -174,7 +174,7 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
|
|||||||
|
|
||||||
const revisionInSecondary = await (
|
const revisionInSecondary = await (
|
||||||
this.secondRevisionsRepository as RevisionRepositoryInterface
|
this.secondRevisionsRepository as RevisionRepositoryInterface
|
||||||
).findOneByUuid(revisionUuid, userUuid)
|
).findOneByUuid(revisionUuid, userUuid, [])
|
||||||
if (!revisionInSecondary) {
|
if (!revisionInSecondary) {
|
||||||
return Result.fail(`Revision ${revision.id.toString()} not found in secondary database`)
|
return Result.fail(`Revision ${revision.id.toString()} not found in secondary database`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,13 +65,16 @@ export class BaseRevisionsController extends BaseHttpController {
|
|||||||
revisionUuid: request.params.uuid,
|
revisionUuid: request.params.uuid,
|
||||||
userUuid: response.locals.user.uuid,
|
userUuid: response.locals.user.uuid,
|
||||||
roleNames: response.locals.roles.map((role: Role) => role.name),
|
roleNames: response.locals.roles.map((role: Role) => role.name),
|
||||||
|
sharedVaultUuids: response.locals.belongsToSharedVaults.map(
|
||||||
|
(association: { shared_vault_uuid: string; permission: string }) => association.shared_vault_uuid,
|
||||||
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
if (revisionOrError.isFailed()) {
|
if (revisionOrError.isFailed()) {
|
||||||
return this.json(
|
return this.json(
|
||||||
{
|
{
|
||||||
error: {
|
error: {
|
||||||
message: 'Could not retrieve revision.',
|
message: revisionOrError.getError(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
HttpStatusCode.BadRequest,
|
HttpStatusCode.BadRequest,
|
||||||
|
|||||||
@@ -16,6 +16,21 @@ export class MongoDBRevisionRepository implements RevisionRepositoryInterface {
|
|||||||
private logger: Logger,
|
private logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
async clearSharedVaultAndKeySystemAssociations(itemUuid: Uuid, sharedVaultUuid: Uuid): Promise<void> {
|
||||||
|
await this.mongoRepository.updateMany(
|
||||||
|
{
|
||||||
|
itemUuid: { $eq: itemUuid.value },
|
||||||
|
sharedVaultUuid: { $eq: sharedVaultUuid.value },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$set: {
|
||||||
|
sharedVaultUuid: null,
|
||||||
|
keySystemIdentifier: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
async countByUserUuid(userUuid: Uuid): Promise<number> {
|
async countByUserUuid(userUuid: Uuid): Promise<number> {
|
||||||
return this.mongoRepository.count({ userUuid: { $eq: userUuid.value } })
|
return this.mongoRepository.count({ userUuid: { $eq: userUuid.value } })
|
||||||
}
|
}
|
||||||
@@ -49,15 +64,32 @@ export class MongoDBRevisionRepository implements RevisionRepositoryInterface {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async findOneByUuid(revisionUuid: Uuid, userUuid: Uuid): Promise<Revision | null> {
|
async findOneByUuid(revisionUuid: Uuid, userUuid: Uuid, sharedVaultUuids: Uuid[]): Promise<Revision | null> {
|
||||||
const persistence = await this.mongoRepository.findOne({
|
let persistence = null
|
||||||
where: {
|
if (sharedVaultUuids.length > 0) {
|
||||||
$and: [
|
persistence = await this.mongoRepository.findOne({
|
||||||
{ _id: { $eq: BSON.UUID.createFromHexString(revisionUuid.value) } },
|
where: {
|
||||||
{ userUuid: { $eq: userUuid.value } },
|
$and: [
|
||||||
],
|
{ _id: { $eq: BSON.UUID.createFromHexString(revisionUuid.value) } },
|
||||||
},
|
{
|
||||||
})
|
$or: [
|
||||||
|
{ sharedVaultUuid: { $in: sharedVaultUuids.map((uuid) => uuid.value) } },
|
||||||
|
{ userUuid: { $eq: userUuid.value } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
persistence = await this.mongoRepository.findOne({
|
||||||
|
where: {
|
||||||
|
$and: [
|
||||||
|
{ _id: { $eq: BSON.UUID.createFromHexString(revisionUuid.value) } },
|
||||||
|
{ userUuid: { $eq: userUuid.value } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (persistence === null) {
|
if (persistence === null) {
|
||||||
return null
|
return null
|
||||||
@@ -98,7 +130,12 @@ export class MongoDBRevisionRepository implements RevisionRepositoryInterface {
|
|||||||
where: {
|
where: {
|
||||||
$and: [
|
$and: [
|
||||||
{ itemUuid: { $eq: itemUuid.value } },
|
{ itemUuid: { $eq: itemUuid.value } },
|
||||||
{ sharedVaultUuid: { $in: sharedVaultUuids.map((uuid) => uuid.value) } },
|
{
|
||||||
|
$or: [
|
||||||
|
{ sharedVaultUuid: { $in: sharedVaultUuids.map((uuid) => uuid.value) } },
|
||||||
|
{ userUuid: { $eq: userUuid.value } },
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
order: {
|
order: {
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ export class SQLLegacyRevisionRepository implements RevisionRepositoryInterface
|
|||||||
protected logger: Logger,
|
protected logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
async clearSharedVaultAndKeySystemAssociations(_itemUuid: Uuid, _sharedVaultUuid: Uuid): Promise<void> {
|
||||||
|
this.logger.error('Method clearSharedVaultAndKeySystemAssociations not implemented.')
|
||||||
|
}
|
||||||
|
|
||||||
async countByUserUuid(userUuid: Uuid): Promise<number> {
|
async countByUserUuid(userUuid: Uuid): Promise<number> {
|
||||||
return this.ormRepository
|
return this.ormRepository
|
||||||
.createQueryBuilder()
|
.createQueryBuilder()
|
||||||
@@ -92,7 +96,7 @@ export class SQLLegacyRevisionRepository implements RevisionRepositoryInterface
|
|||||||
.execute()
|
.execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
async findOneByUuid(revisionUuid: Uuid, userUuid: Uuid): Promise<Revision | null> {
|
async findOneByUuid(revisionUuid: Uuid, userUuid: Uuid, _sharedVaultUuids: Uuid[]): Promise<Revision | null> {
|
||||||
const SQLLegacyRevision = await this.ormRepository
|
const SQLLegacyRevision = await this.ormRepository
|
||||||
.createQueryBuilder()
|
.createQueryBuilder()
|
||||||
.where('uuid = :revisionUuid', { revisionUuid: revisionUuid.value })
|
.where('uuid = :revisionUuid', { revisionUuid: revisionUuid.value })
|
||||||
|
|||||||
@@ -17,6 +17,49 @@ export class SQLRevisionRepository extends SQLLegacyRevisionRepository {
|
|||||||
super(ormRepository, revisionMetadataMapper, revisionMapper, logger)
|
super(ormRepository, revisionMetadataMapper, revisionMapper, logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override async findOneByUuid(revisionUuid: Uuid, userUuid: Uuid, sharedVaultUuids: Uuid[]): Promise<Revision | null> {
|
||||||
|
const queryBuilder = this.ormRepository.createQueryBuilder()
|
||||||
|
|
||||||
|
if (sharedVaultUuids.length > 0) {
|
||||||
|
queryBuilder.where(
|
||||||
|
'uuid = :revisionUuid AND (user_uuid = :userUuid OR shared_vault_uuid IN (:...sharedVaultUuids))',
|
||||||
|
{
|
||||||
|
revisionUuid: revisionUuid.value,
|
||||||
|
userUuid: userUuid.value,
|
||||||
|
sharedVaultUuids: sharedVaultUuids.map((uuid) => uuid.value),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
queryBuilder.where('uuid = :revisionUuid AND user_uuid = :userUuid', {
|
||||||
|
revisionUuid: revisionUuid.value,
|
||||||
|
userUuid: userUuid.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const sqlRevision = await queryBuilder.getOne()
|
||||||
|
|
||||||
|
if (sqlRevision === null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.revisionMapper.toDomain(sqlRevision)
|
||||||
|
}
|
||||||
|
|
||||||
|
override async clearSharedVaultAndKeySystemAssociations(itemUuid: Uuid, sharedVaultUuid: Uuid): Promise<void> {
|
||||||
|
await this.ormRepository
|
||||||
|
.createQueryBuilder()
|
||||||
|
.update()
|
||||||
|
.set({
|
||||||
|
sharedVaultUuid: null,
|
||||||
|
keySystemIdentifier: null,
|
||||||
|
})
|
||||||
|
.where('item_uuid = :itemUuid AND shared_vault_uuid = :sharedVaultUuid', {
|
||||||
|
itemUuid: itemUuid.value,
|
||||||
|
sharedVaultUuid: sharedVaultUuid.value,
|
||||||
|
})
|
||||||
|
.execute()
|
||||||
|
}
|
||||||
|
|
||||||
override async findMetadataByItemId(
|
override async findMetadataByItemId(
|
||||||
itemUuid: Uuid,
|
itemUuid: Uuid,
|
||||||
userUuid: Uuid,
|
userUuid: Uuid,
|
||||||
@@ -28,13 +71,21 @@ export class SQLRevisionRepository extends SQLLegacyRevisionRepository {
|
|||||||
.addSelect('content_type', 'contentType')
|
.addSelect('content_type', 'contentType')
|
||||||
.addSelect('created_at', 'createdAt')
|
.addSelect('created_at', 'createdAt')
|
||||||
.addSelect('updated_at', 'updatedAt')
|
.addSelect('updated_at', 'updatedAt')
|
||||||
.where('item_uuid = :itemUuid AND user_uuid = :userUuid', { itemUuid: itemUuid.value, userUuid: userUuid.value })
|
|
||||||
.orderBy('created_at', 'DESC')
|
.orderBy('created_at', 'DESC')
|
||||||
|
|
||||||
if (sharedVaultUuids.length > 0) {
|
if (sharedVaultUuids.length > 0) {
|
||||||
queryBuilder.orWhere('item_uuid = :itemUuid AND shared_vault_uuid IN (:...sharedVaultUuids)', {
|
queryBuilder.where(
|
||||||
|
'item_uuid = :itemUuid AND (user_uuid = :userUuid OR shared_vault_uuid IN (:...sharedVaultUuids))',
|
||||||
|
{
|
||||||
|
itemUuid: itemUuid.value,
|
||||||
|
userUuid: userUuid.value,
|
||||||
|
sharedVaultUuids: sharedVaultUuids.map((uuid) => uuid.value),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
queryBuilder.where('item_uuid = :itemUuid AND user_uuid = :userUuid', {
|
||||||
itemUuid: itemUuid.value,
|
itemUuid: itemUuid.value,
|
||||||
sharedVaultUuids: sharedVaultUuids.map((uuid) => uuid.value),
|
userUuid: userUuid.value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,16 @@ export class RevisionHttpMapper implements MapperInterface<Revision, RevisionHtt
|
|||||||
auth_hash: domain.props.authHash,
|
auth_hash: domain.props.authHash,
|
||||||
created_at: domain.props.dates.createdAt.toISOString(),
|
created_at: domain.props.dates.createdAt.toISOString(),
|
||||||
updated_at: domain.props.dates.updatedAt.toISOString(),
|
updated_at: domain.props.dates.updatedAt.toISOString(),
|
||||||
|
key_system_identifier: domain.props.keySystemAssociation
|
||||||
|
? domain.props.keySystemAssociation.props.keySystemIdentifier
|
||||||
|
: null,
|
||||||
|
shared_vault_uuid: domain.props.sharedVaultAssociation
|
||||||
|
? domain.props.sharedVaultAssociation.props.sharedVaultUuid.value
|
||||||
|
: null,
|
||||||
|
last_edited_by_uuid: domain.props.sharedVaultAssociation
|
||||||
|
? domain.props.sharedVaultAssociation.props.editedBy.value
|
||||||
|
: null,
|
||||||
|
user_uuid: domain.props.userUuid ? domain.props.userUuid.value : null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,4 +8,8 @@ export interface RevisionHttpRepresentation {
|
|||||||
auth_hash: string | null
|
auth_hash: string | null
|
||||||
created_at: string
|
created_at: string
|
||||||
updated_at: string
|
updated_at: string
|
||||||
|
key_system_identifier: string | null
|
||||||
|
shared_vault_uuid: string | null
|
||||||
|
user_uuid: string | null
|
||||||
|
last_edited_by_uuid: string | null
|
||||||
}
|
}
|
||||||
|
|||||||
+47
-1
@@ -1,8 +1,10 @@
|
|||||||
import { MapperInterface, Dates, UniqueEntityId, Uuid, ContentType } from '@standardnotes/domain-core'
|
import { MapperInterface, Dates, UniqueEntityId, Uuid, ContentType } from '@standardnotes/domain-core'
|
||||||
|
import { BSON } from 'mongodb'
|
||||||
|
|
||||||
import { MongoDBRevision } from '../../../Infra/TypeORM/MongoDB/MongoDBRevision'
|
import { MongoDBRevision } from '../../../Infra/TypeORM/MongoDB/MongoDBRevision'
|
||||||
import { Revision } from '../../../Domain/Revision/Revision'
|
import { Revision } from '../../../Domain/Revision/Revision'
|
||||||
import { BSON } from 'mongodb'
|
import { SharedVaultAssociation } from '../../../Domain/SharedVault/SharedVaultAssociation'
|
||||||
|
import { KeySystemAssociation } from '../../../Domain/KeySystem/KeySystemAssociation'
|
||||||
|
|
||||||
export class MongoDBRevisionPersistenceMapper implements MapperInterface<Revision, MongoDBRevision> {
|
export class MongoDBRevisionPersistenceMapper implements MapperInterface<Revision, MongoDBRevision> {
|
||||||
toDomain(projection: MongoDBRevision): Revision {
|
toDomain(projection: MongoDBRevision): Revision {
|
||||||
@@ -33,6 +35,39 @@ export class MongoDBRevisionPersistenceMapper implements MapperInterface<Revisio
|
|||||||
userUuid = userUuidOrError.getValue()
|
userUuid = userUuidOrError.getValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let sharedVaultAssociation: SharedVaultAssociation | undefined = undefined
|
||||||
|
if (projection.sharedVaultUuid && projection.editedBy) {
|
||||||
|
const sharedVaultUuidOrError = Uuid.create(projection.sharedVaultUuid)
|
||||||
|
if (sharedVaultUuidOrError.isFailed()) {
|
||||||
|
throw new Error(`Failed to create revision from projection: ${sharedVaultUuidOrError.getError()}`)
|
||||||
|
}
|
||||||
|
const sharedVaultUuid = sharedVaultUuidOrError.getValue()
|
||||||
|
|
||||||
|
const lastEditedByOrError = Uuid.create(projection.editedBy)
|
||||||
|
if (lastEditedByOrError.isFailed()) {
|
||||||
|
throw new Error(`Failed to create revision from projection: ${lastEditedByOrError.getError()}`)
|
||||||
|
}
|
||||||
|
const lastEditedBy = lastEditedByOrError.getValue()
|
||||||
|
|
||||||
|
const sharedVaultAssociationOrError = SharedVaultAssociation.create({
|
||||||
|
sharedVaultUuid,
|
||||||
|
editedBy: lastEditedBy,
|
||||||
|
})
|
||||||
|
if (sharedVaultAssociationOrError.isFailed()) {
|
||||||
|
throw new Error(`Failed to create revision from projection: ${sharedVaultAssociationOrError.getError()}`)
|
||||||
|
}
|
||||||
|
sharedVaultAssociation = sharedVaultAssociationOrError.getValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
let keySystemAssociation: KeySystemAssociation | undefined = undefined
|
||||||
|
if (projection.keySystemIdentifier) {
|
||||||
|
const keySystemAssociationOrError = KeySystemAssociation.create(projection.keySystemIdentifier)
|
||||||
|
if (keySystemAssociationOrError.isFailed()) {
|
||||||
|
throw new Error(`Failed to create revision from projection: ${keySystemAssociationOrError.getError()}`)
|
||||||
|
}
|
||||||
|
keySystemAssociation = keySystemAssociationOrError.getValue()
|
||||||
|
}
|
||||||
|
|
||||||
const revisionOrError = Revision.create(
|
const revisionOrError = Revision.create(
|
||||||
{
|
{
|
||||||
authHash: projection.authHash,
|
authHash: projection.authHash,
|
||||||
@@ -44,6 +79,8 @@ export class MongoDBRevisionPersistenceMapper implements MapperInterface<Revisio
|
|||||||
itemUuid,
|
itemUuid,
|
||||||
userUuid,
|
userUuid,
|
||||||
dates,
|
dates,
|
||||||
|
sharedVaultAssociation,
|
||||||
|
keySystemAssociation,
|
||||||
},
|
},
|
||||||
new UniqueEntityId(projection._id.toHexString()),
|
new UniqueEntityId(projection._id.toHexString()),
|
||||||
)
|
)
|
||||||
@@ -67,6 +104,15 @@ export class MongoDBRevisionPersistenceMapper implements MapperInterface<Revisio
|
|||||||
mongoDBRevision.itemUuid = domain.props.itemUuid.value
|
mongoDBRevision.itemUuid = domain.props.itemUuid.value
|
||||||
mongoDBRevision.itemsKeyId = domain.props.itemsKeyId
|
mongoDBRevision.itemsKeyId = domain.props.itemsKeyId
|
||||||
mongoDBRevision.userUuid = domain.props.userUuid ? domain.props.userUuid.value : null
|
mongoDBRevision.userUuid = domain.props.userUuid ? domain.props.userUuid.value : null
|
||||||
|
mongoDBRevision.sharedVaultUuid = domain.props.sharedVaultAssociation
|
||||||
|
? domain.props.sharedVaultAssociation.props.sharedVaultUuid.value
|
||||||
|
: null
|
||||||
|
mongoDBRevision.editedBy = domain.props.sharedVaultAssociation
|
||||||
|
? domain.props.sharedVaultAssociation.props.editedBy.value
|
||||||
|
: null
|
||||||
|
mongoDBRevision.keySystemIdentifier = domain.props.keySystemAssociation
|
||||||
|
? domain.props.keySystemAssociation.props.keySystemIdentifier
|
||||||
|
: null
|
||||||
mongoDBRevision._id = BSON.UUID.createFromHexString(domain.id.toString())
|
mongoDBRevision._id = BSON.UUID.createFromHexString(domain.id.toString())
|
||||||
|
|
||||||
return mongoDBRevision
|
return mongoDBRevision
|
||||||
|
|||||||
@@ -2,6 +2,5 @@
|
|||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
sh supervisor/wait-for.sh $DB_HOST $DB_PORT
|
sh supervisor/wait-for.sh localhost $SYNCING_SERVER_PORT
|
||||||
sh supervisor/wait-for.sh $REDIS_HOST $REDIS_PORT
|
|
||||||
node docker/entrypoint-server.js
|
node docker/entrypoint-server.js
|
||||||
|
|||||||
@@ -3,6 +3,18 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.20.39](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.20.38...@standardnotes/scheduler-server@1.20.39) (2023-09-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||||
|
|
||||||
|
## [1.20.38](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.20.37...@standardnotes/scheduler-server@1.20.38) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||||
|
|
||||||
|
## [1.20.37](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.20.36...@standardnotes/scheduler-server@1.20.37) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||||
|
|
||||||
## [1.20.36](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.20.35...@standardnotes/scheduler-server@1.20.36) (2023-09-06)
|
## [1.20.36](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.20.35...@standardnotes/scheduler-server@1.20.36) (2023-09-06)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/scheduler-server",
|
"name": "@standardnotes/scheduler-server",
|
||||||
"version": "1.20.36",
|
"version": "1.20.39",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.21.30](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.21.29...@standardnotes/settings@1.21.30) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/settings
|
||||||
|
|
||||||
## [1.21.29](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.21.28...@standardnotes/settings@1.21.29) (2023-09-06)
|
## [1.21.29](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.21.28...@standardnotes/settings@1.21.29) (2023-09-06)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/settings
|
**Note:** Version bump only for package @standardnotes/settings
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/settings",
|
"name": "@standardnotes/settings",
|
||||||
"version": "1.21.29",
|
"version": "1.21.30",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,34 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [1.95.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.94.0...@standardnotes/syncing-server@1.95.0) (2023-09-08)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* transition users after sign out ([398338c](https://github.com/standardnotes/syncing-server-js/commit/398338c8f81b12406c7ab3bf1654e60b94d7cfd0))
|
||||||
|
|
||||||
|
# [1.94.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.93.1...@standardnotes/syncing-server@1.94.0) (2023-09-08)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **syncing-server:** add procedure to trigger transition for specific user ([8cb92d9](https://github.com/standardnotes/syncing-server-js/commit/8cb92d9678cffe9188fa2b038f1b5a9e0247551e))
|
||||||
|
|
||||||
|
## [1.93.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.93.0...@standardnotes/syncing-server@1.93.1) (2023-09-07)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **syncing-server:** invalidating cache for user removed from shared vault ([#812](https://github.com/standardnotes/syncing-server-js/issues/812)) ([c4a1502](https://github.com/standardnotes/syncing-server-js/commit/c4a1502f70e675da5c81c4005ee1eca578a7e3f4))
|
||||||
|
|
||||||
|
# [1.93.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.92.1...@standardnotes/syncing-server@1.93.0) (2023-09-07)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add removing revisions from shared vaults ([#811](https://github.com/standardnotes/syncing-server-js/issues/811)) ([3bd63f7](https://github.com/standardnotes/syncing-server-js/commit/3bd63f767464baf9b9f1ffa52eea9eed4a4e11b5))
|
||||||
|
|
||||||
|
## [1.92.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.92.0...@standardnotes/syncing-server@1.92.1) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||||
|
|
||||||
# [1.92.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.91.3...@standardnotes/syncing-server@1.92.0) (2023-09-06)
|
# [1.92.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.91.3...@standardnotes/syncing-server@1.92.0) (2023-09-06)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
import 'reflect-metadata'
|
||||||
|
|
||||||
|
import { Logger } from 'winston'
|
||||||
|
|
||||||
|
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
||||||
|
import TYPES from '../src/Bootstrap/Types'
|
||||||
|
import { Env } from '../src/Bootstrap/Env'
|
||||||
|
import { TriggerTransitionFromPrimaryToSecondaryDatabaseForUser } from '../src/Domain/UseCase/Transition/TriggerTransitionFromPrimaryToSecondaryDatabaseForUser/TriggerTransitionFromPrimaryToSecondaryDatabaseForUser'
|
||||||
|
|
||||||
|
const inputArgs = process.argv.slice(2)
|
||||||
|
const userUuid = inputArgs[0]
|
||||||
|
|
||||||
|
const requestTransition = async (
|
||||||
|
triggerTransitionFromPrimaryToSecondaryDatabaseForUser: TriggerTransitionFromPrimaryToSecondaryDatabaseForUser,
|
||||||
|
logger: Logger,
|
||||||
|
): Promise<void> => {
|
||||||
|
const result = await triggerTransitionFromPrimaryToSecondaryDatabaseForUser.execute({
|
||||||
|
userUuid,
|
||||||
|
})
|
||||||
|
if (result.isFailed()) {
|
||||||
|
logger.error(`Could not trigger transition for user ${userUuid}: ${result.getError()}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const container = new ContainerConfigLoader()
|
||||||
|
void container.load().then((container) => {
|
||||||
|
const env: Env = new Env()
|
||||||
|
env.load()
|
||||||
|
|
||||||
|
const logger: Logger = container.get(TYPES.Sync_Logger)
|
||||||
|
|
||||||
|
logger.info(`Starting transitiong for user ${userUuid} ...`)
|
||||||
|
|
||||||
|
const triggerTransitionFromPrimaryToSecondaryDatabaseForUser: TriggerTransitionFromPrimaryToSecondaryDatabaseForUser =
|
||||||
|
container.get(TYPES.Sync_TriggerTransitionFromPrimaryToSecondaryDatabaseForUser)
|
||||||
|
|
||||||
|
Promise.resolve(requestTransition(triggerTransitionFromPrimaryToSecondaryDatabaseForUser, logger))
|
||||||
|
.then(() => {
|
||||||
|
logger.info(`Transition triggered for user ${userUuid}`)
|
||||||
|
|
||||||
|
process.exit(0)
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
logger.error(`Could not trigger transition for user ${userUuid}: ${error.message}`)
|
||||||
|
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'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
|
||||||
@@ -14,6 +14,12 @@ case "$COMMAND" in
|
|||||||
node docker/entrypoint-worker.js
|
node docker/entrypoint-worker.js
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
'transition' )
|
||||||
|
echo "[Docker] Starting transition Single User..."
|
||||||
|
USER_UUID=$1 && shift 1
|
||||||
|
node docker/entrypoint-transition.js $USER_UUID
|
||||||
|
;;
|
||||||
|
|
||||||
* )
|
* )
|
||||||
echo "[Docker] Unknown command"
|
echo "[Docker] Unknown command"
|
||||||
;;
|
;;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/syncing-server",
|
"name": "@standardnotes/syncing-server",
|
||||||
"version": "1.92.0",
|
"version": "1.95.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -166,6 +166,7 @@ import { SQLItem } from '../Infra/TypeORM/SQLItem'
|
|||||||
import { SQLItemPersistenceMapper } from '../Mapping/Persistence/SQLItemPersistenceMapper'
|
import { SQLItemPersistenceMapper } from '../Mapping/Persistence/SQLItemPersistenceMapper'
|
||||||
import { SQLItemRepository } from '../Infra/TypeORM/SQLItemRepository'
|
import { SQLItemRepository } from '../Infra/TypeORM/SQLItemRepository'
|
||||||
import { SendEventToClient } from '../Domain/UseCase/Syncing/SendEventToClient/SendEventToClient'
|
import { SendEventToClient } from '../Domain/UseCase/Syncing/SendEventToClient/SendEventToClient'
|
||||||
|
import { TransitionRequestedEventHandler } from '../Domain/Handler/TransitionRequestedEventHandler'
|
||||||
|
|
||||||
export class ContainerConfigLoader {
|
export class ContainerConfigLoader {
|
||||||
private readonly DEFAULT_CONTENT_SIZE_TRANSFER_LIMIT = 10_000_000
|
private readonly DEFAULT_CONTENT_SIZE_TRANSFER_LIMIT = 10_000_000
|
||||||
@@ -955,6 +956,16 @@ export class ContainerConfigLoader {
|
|||||||
container.get<Logger>(TYPES.Sync_Logger),
|
container.get<Logger>(TYPES.Sync_Logger),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
container
|
||||||
|
.bind<TransitionRequestedEventHandler>(TYPES.Sync_TransitionRequestedEventHandler)
|
||||||
|
.toConstantValue(
|
||||||
|
new TransitionRequestedEventHandler(
|
||||||
|
container.get<TriggerTransitionFromPrimaryToSecondaryDatabaseForUser>(
|
||||||
|
TYPES.Sync_TriggerTransitionFromPrimaryToSecondaryDatabaseForUser,
|
||||||
|
),
|
||||||
|
container.get<Logger>(TYPES.Sync_Logger),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
// Services
|
// Services
|
||||||
container.bind<ContentDecoder>(TYPES.Sync_ContentDecoder).toDynamicValue(() => new ContentDecoder())
|
container.bind<ContentDecoder>(TYPES.Sync_ContentDecoder).toDynamicValue(() => new ContentDecoder())
|
||||||
@@ -993,6 +1004,10 @@ export class ContainerConfigLoader {
|
|||||||
'TRANSITION_STATUS_UPDATED',
|
'TRANSITION_STATUS_UPDATED',
|
||||||
container.get<TransitionStatusUpdatedEventHandler>(TYPES.Sync_TransitionStatusUpdatedEventHandler),
|
container.get<TransitionStatusUpdatedEventHandler>(TYPES.Sync_TransitionStatusUpdatedEventHandler),
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'TRANSITION_REQUESTED',
|
||||||
|
container.get<TransitionRequestedEventHandler>(TYPES.Sync_TransitionRequestedEventHandler),
|
||||||
|
],
|
||||||
])
|
])
|
||||||
if (!isConfiguredForHomeServer) {
|
if (!isConfiguredForHomeServer) {
|
||||||
container.bind(TYPES.Sync_AUTH_SERVER_URL).toConstantValue(env.get('AUTH_SERVER_URL'))
|
container.bind(TYPES.Sync_AUTH_SERVER_URL).toConstantValue(env.get('AUTH_SERVER_URL'))
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ const TYPES = {
|
|||||||
Sync_SharedVaultFileUploadedEventHandler: Symbol.for('Sync_SharedVaultFileUploadedEventHandler'),
|
Sync_SharedVaultFileUploadedEventHandler: Symbol.for('Sync_SharedVaultFileUploadedEventHandler'),
|
||||||
Sync_SharedVaultFileMovedEventHandler: Symbol.for('Sync_SharedVaultFileMovedEventHandler'),
|
Sync_SharedVaultFileMovedEventHandler: Symbol.for('Sync_SharedVaultFileMovedEventHandler'),
|
||||||
Sync_TransitionStatusUpdatedEventHandler: Symbol.for('Sync_TransitionStatusUpdatedEventHandler'),
|
Sync_TransitionStatusUpdatedEventHandler: Symbol.for('Sync_TransitionStatusUpdatedEventHandler'),
|
||||||
|
Sync_TransitionRequestedEventHandler: Symbol.for('Sync_TransitionRequestedEventHandler'),
|
||||||
// Services
|
// Services
|
||||||
Sync_ContentDecoder: Symbol.for('Sync_ContentDecoder'),
|
Sync_ContentDecoder: Symbol.for('Sync_ContentDecoder'),
|
||||||
Sync_DomainEventPublisher: Symbol.for('Sync_DomainEventPublisher'),
|
Sync_DomainEventPublisher: Symbol.for('Sync_DomainEventPublisher'),
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
DuplicateItemSyncedEvent,
|
DuplicateItemSyncedEvent,
|
||||||
EmailRequestedEvent,
|
EmailRequestedEvent,
|
||||||
ItemDumpedEvent,
|
ItemDumpedEvent,
|
||||||
|
ItemRemovedFromSharedVaultEvent,
|
||||||
ItemRevisionCreationRequestedEvent,
|
ItemRevisionCreationRequestedEvent,
|
||||||
MessageSentToUserEvent,
|
MessageSentToUserEvent,
|
||||||
NotificationAddedForUserEvent,
|
NotificationAddedForUserEvent,
|
||||||
@@ -20,6 +21,26 @@ import { DomainEventFactoryInterface } from './DomainEventFactoryInterface'
|
|||||||
export class DomainEventFactory implements DomainEventFactoryInterface {
|
export class DomainEventFactory implements DomainEventFactoryInterface {
|
||||||
constructor(private timer: TimerInterface) {}
|
constructor(private timer: TimerInterface) {}
|
||||||
|
|
||||||
|
createItemRemovedFromSharedVaultEvent(dto: {
|
||||||
|
sharedVaultUuid: string
|
||||||
|
itemUuid: string
|
||||||
|
userUuid: string
|
||||||
|
roleNames: string[]
|
||||||
|
}): ItemRemovedFromSharedVaultEvent {
|
||||||
|
return {
|
||||||
|
type: 'ITEM_REMOVED_FROM_SHARED_VAULT',
|
||||||
|
createdAt: this.timer.getUTCDate(),
|
||||||
|
meta: {
|
||||||
|
correlation: {
|
||||||
|
userIdentifier: dto.userUuid,
|
||||||
|
userIdentifierType: 'uuid',
|
||||||
|
},
|
||||||
|
origin: DomainEventService.SyncingServer,
|
||||||
|
},
|
||||||
|
payload: dto,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
createUserRemovedFromSharedVaultEvent(dto: {
|
createUserRemovedFromSharedVaultEvent(dto: {
|
||||||
sharedVaultUuid: string
|
sharedVaultUuid: string
|
||||||
userUuid: string
|
userUuid: string
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import {
|
|||||||
DuplicateItemSyncedEvent,
|
DuplicateItemSyncedEvent,
|
||||||
EmailRequestedEvent,
|
EmailRequestedEvent,
|
||||||
ItemDumpedEvent,
|
ItemDumpedEvent,
|
||||||
|
ItemRemovedFromSharedVaultEvent,
|
||||||
ItemRevisionCreationRequestedEvent,
|
ItemRevisionCreationRequestedEvent,
|
||||||
MessageSentToUserEvent,
|
MessageSentToUserEvent,
|
||||||
NotificationAddedForUserEvent,
|
NotificationAddedForUserEvent,
|
||||||
@@ -93,4 +94,10 @@ export interface DomainEventFactoryInterface {
|
|||||||
sharedVaultUuid: string
|
sharedVaultUuid: string
|
||||||
userUuid: string
|
userUuid: string
|
||||||
}): UserRemovedFromSharedVaultEvent
|
}): UserRemovedFromSharedVaultEvent
|
||||||
|
createItemRemovedFromSharedVaultEvent(dto: {
|
||||||
|
sharedVaultUuid: string
|
||||||
|
itemUuid: string
|
||||||
|
userUuid: string
|
||||||
|
roleNames: string[]
|
||||||
|
}): ItemRemovedFromSharedVaultEvent
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { DomainEventHandlerInterface, TransitionRequestedEvent } from '@standardnotes/domain-events'
|
||||||
|
import { Logger } from 'winston'
|
||||||
|
|
||||||
|
import { TriggerTransitionFromPrimaryToSecondaryDatabaseForUser } from '../UseCase/Transition/TriggerTransitionFromPrimaryToSecondaryDatabaseForUser/TriggerTransitionFromPrimaryToSecondaryDatabaseForUser'
|
||||||
|
|
||||||
|
export class TransitionRequestedEventHandler implements DomainEventHandlerInterface {
|
||||||
|
constructor(
|
||||||
|
private triggerTransitionFromPrimaryToSecondaryDatabaseForUser: TriggerTransitionFromPrimaryToSecondaryDatabaseForUser,
|
||||||
|
private logger: Logger,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async handle(event: TransitionRequestedEvent): Promise<void> {
|
||||||
|
this.logger.info(`Handling transition requested event for user ${event.payload.userUuid}`)
|
||||||
|
|
||||||
|
const result = await this.triggerTransitionFromPrimaryToSecondaryDatabaseForUser.execute({
|
||||||
|
userUuid: event.payload.userUuid,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (result.isFailed()) {
|
||||||
|
this.logger.error(`Failed to trigger transition for user ${event.payload.userUuid}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+44
@@ -111,6 +111,9 @@ describe('UpdateExistingItem', () => {
|
|||||||
domainEventFactory.createItemRevisionCreationRequested = jest
|
domainEventFactory.createItemRevisionCreationRequested = jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockReturnValue({} as jest.Mocked<DomainEventInterface>)
|
.mockReturnValue({} as jest.Mocked<DomainEventInterface>)
|
||||||
|
domainEventFactory.createItemRemovedFromSharedVaultEvent = jest
|
||||||
|
.fn()
|
||||||
|
.mockReturnValue({} as jest.Mocked<DomainEventInterface>)
|
||||||
|
|
||||||
determineSharedVaultOperationOnItem = {} as jest.Mocked<DetermineSharedVaultOperationOnItem>
|
determineSharedVaultOperationOnItem = {} as jest.Mocked<DetermineSharedVaultOperationOnItem>
|
||||||
determineSharedVaultOperationOnItem.execute = jest.fn().mockResolvedValue(
|
determineSharedVaultOperationOnItem.execute = jest.fn().mockResolvedValue(
|
||||||
@@ -400,6 +403,47 @@ describe('UpdateExistingItem', () => {
|
|||||||
expect(item1.props.sharedVaultAssociation).not.toBeUndefined()
|
expect(item1.props.sharedVaultAssociation).not.toBeUndefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should remove a shared vault association and publish an event that item has been removed from shared vault', async () => {
|
||||||
|
const useCase = createUseCase()
|
||||||
|
|
||||||
|
item1.props.sharedVaultAssociation = SharedVaultAssociation.create({
|
||||||
|
sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
|
||||||
|
lastEditedBy: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
|
||||||
|
}).getValue()
|
||||||
|
|
||||||
|
const itemHash = ItemHash.create({
|
||||||
|
...itemHash1.props,
|
||||||
|
shared_vault_uuid: null,
|
||||||
|
}).getValue()
|
||||||
|
|
||||||
|
determineSharedVaultOperationOnItem.execute = jest.fn().mockReturnValue(
|
||||||
|
Result.ok(
|
||||||
|
SharedVaultOperationOnItem.create({
|
||||||
|
existingItem: item1,
|
||||||
|
incomingItemHash: itemHash1,
|
||||||
|
sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
|
||||||
|
type: SharedVaultOperationOnItem.TYPES.RemoveFromSharedVault,
|
||||||
|
userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
|
||||||
|
}).getValue(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
const result = await useCase.execute({
|
||||||
|
existingItem: item1,
|
||||||
|
itemHash,
|
||||||
|
sessionUuid: '00000000-0000-0000-0000-000000000000',
|
||||||
|
performingUserUuid: '00000000-0000-0000-0000-000000000000',
|
||||||
|
roleNames: [RoleName.NAMES.CoreUser],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result.isFailed()).toBeFalsy()
|
||||||
|
|
||||||
|
expect(item1.props.sharedVaultAssociation).toBeUndefined()
|
||||||
|
|
||||||
|
expect(domainEventFactory.createItemRemovedFromSharedVaultEvent).toHaveBeenCalled()
|
||||||
|
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
it('should return error if shared vault association could not be created', async () => {
|
it('should return error if shared vault association could not be created', async () => {
|
||||||
const useCase = createUseCase()
|
const useCase = createUseCase()
|
||||||
|
|
||||||
|
|||||||
+36
-25
@@ -37,16 +37,6 @@ export class UpdateExistingItem implements UseCaseInterface<Item> {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
async execute(dto: UpdateExistingItemDTO): Promise<Result<Item>> {
|
async execute(dto: UpdateExistingItemDTO): Promise<Result<Item>> {
|
||||||
let sessionUuid = null
|
|
||||||
if (dto.sessionUuid) {
|
|
||||||
const sessionUuidOrError = Uuid.create(dto.sessionUuid)
|
|
||||||
if (sessionUuidOrError.isFailed()) {
|
|
||||||
return Result.fail(sessionUuidOrError.getError())
|
|
||||||
}
|
|
||||||
sessionUuid = sessionUuidOrError.getValue()
|
|
||||||
}
|
|
||||||
dto.existingItem.props.updatedWithSession = sessionUuid
|
|
||||||
|
|
||||||
const userUuidOrError = Uuid.create(dto.performingUserUuid)
|
const userUuidOrError = Uuid.create(dto.performingUserUuid)
|
||||||
if (userUuidOrError.isFailed()) {
|
if (userUuidOrError.isFailed()) {
|
||||||
return Result.fail(userUuidOrError.getError())
|
return Result.fail(userUuidOrError.getError())
|
||||||
@@ -59,6 +49,29 @@ export class UpdateExistingItem implements UseCaseInterface<Item> {
|
|||||||
}
|
}
|
||||||
const roleNames = roleNamesOrError.getValue()
|
const roleNames = roleNamesOrError.getValue()
|
||||||
|
|
||||||
|
let sharedVaultOperation: SharedVaultOperationOnItem | null = null
|
||||||
|
if (dto.itemHash.representsASharedVaultItem() || dto.existingItem.isAssociatedWithASharedVault()) {
|
||||||
|
const sharedVaultOperationOrError = await this.determineSharedVaultOperationOnItem.execute({
|
||||||
|
existingItem: dto.existingItem,
|
||||||
|
itemHash: dto.itemHash,
|
||||||
|
userUuid: userUuid.value,
|
||||||
|
})
|
||||||
|
if (sharedVaultOperationOrError.isFailed()) {
|
||||||
|
return Result.fail(sharedVaultOperationOrError.getError())
|
||||||
|
}
|
||||||
|
sharedVaultOperation = sharedVaultOperationOrError.getValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
let sessionUuid = null
|
||||||
|
if (dto.sessionUuid) {
|
||||||
|
const sessionUuidOrError = Uuid.create(dto.sessionUuid)
|
||||||
|
if (sessionUuidOrError.isFailed()) {
|
||||||
|
return Result.fail(sessionUuidOrError.getError())
|
||||||
|
}
|
||||||
|
sessionUuid = sessionUuidOrError.getValue()
|
||||||
|
}
|
||||||
|
dto.existingItem.props.updatedWithSession = sessionUuid
|
||||||
|
|
||||||
if (dto.itemHash.props.content) {
|
if (dto.itemHash.props.content) {
|
||||||
dto.existingItem.props.content = dto.itemHash.props.content
|
dto.existingItem.props.content = dto.itemHash.props.content
|
||||||
}
|
}
|
||||||
@@ -128,7 +141,6 @@ export class UpdateExistingItem implements UseCaseInterface<Item> {
|
|||||||
|
|
||||||
dto.existingItem.props.contentSize = Buffer.byteLength(JSON.stringify(dto.existingItem))
|
dto.existingItem.props.contentSize = Buffer.byteLength(JSON.stringify(dto.existingItem))
|
||||||
|
|
||||||
let sharedVaultOperation: SharedVaultOperationOnItem | null = null
|
|
||||||
if (dto.itemHash.representsASharedVaultItem()) {
|
if (dto.itemHash.representsASharedVaultItem()) {
|
||||||
const sharedVaultAssociationOrError = SharedVaultAssociation.create({
|
const sharedVaultAssociationOrError = SharedVaultAssociation.create({
|
||||||
lastEditedBy: userUuid,
|
lastEditedBy: userUuid,
|
||||||
@@ -140,16 +152,6 @@ export class UpdateExistingItem implements UseCaseInterface<Item> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dto.existingItem.props.sharedVaultAssociation = sharedVaultAssociationOrError.getValue()
|
dto.existingItem.props.sharedVaultAssociation = sharedVaultAssociationOrError.getValue()
|
||||||
|
|
||||||
const sharedVaultOperationOrError = await this.determineSharedVaultOperationOnItem.execute({
|
|
||||||
existingItem: dto.existingItem,
|
|
||||||
itemHash: dto.itemHash,
|
|
||||||
userUuid: userUuid.value,
|
|
||||||
})
|
|
||||||
if (sharedVaultOperationOrError.isFailed()) {
|
|
||||||
return Result.fail(sharedVaultOperationOrError.getError())
|
|
||||||
}
|
|
||||||
sharedVaultOperation = sharedVaultOperationOrError.getValue()
|
|
||||||
} else {
|
} else {
|
||||||
dto.existingItem.props.sharedVaultAssociation = undefined
|
dto.existingItem.props.sharedVaultAssociation = undefined
|
||||||
}
|
}
|
||||||
@@ -209,7 +211,7 @@ export class UpdateExistingItem implements UseCaseInterface<Item> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const notificationsResult = await this.addNotifications(dto.existingItem.uuid, userUuid, sharedVaultOperation)
|
const notificationsResult = await this.addNotificationsAndPublishEvents(userUuid, sharedVaultOperation, dto)
|
||||||
if (notificationsResult.isFailed()) {
|
if (notificationsResult.isFailed()) {
|
||||||
return Result.fail(notificationsResult.getError())
|
return Result.fail(notificationsResult.getError())
|
||||||
}
|
}
|
||||||
@@ -217,10 +219,10 @@ export class UpdateExistingItem implements UseCaseInterface<Item> {
|
|||||||
return Result.ok(dto.existingItem)
|
return Result.ok(dto.existingItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
private async addNotifications(
|
private async addNotificationsAndPublishEvents(
|
||||||
itemUuid: Uuid,
|
|
||||||
userUuid: Uuid,
|
userUuid: Uuid,
|
||||||
sharedVaultOperation: SharedVaultOperationOnItem | null,
|
sharedVaultOperation: SharedVaultOperationOnItem | null,
|
||||||
|
dto: UpdateExistingItemDTO,
|
||||||
): Promise<Result<void>> {
|
): Promise<Result<void>> {
|
||||||
if (
|
if (
|
||||||
sharedVaultOperation &&
|
sharedVaultOperation &&
|
||||||
@@ -229,7 +231,7 @@ export class UpdateExistingItem implements UseCaseInterface<Item> {
|
|||||||
const notificationPayloadOrError = NotificationPayload.create({
|
const notificationPayloadOrError = NotificationPayload.create({
|
||||||
sharedVaultUuid: sharedVaultOperation.props.sharedVaultUuid,
|
sharedVaultUuid: sharedVaultOperation.props.sharedVaultUuid,
|
||||||
type: NotificationType.create(NotificationType.TYPES.SharedVaultItemRemoved).getValue(),
|
type: NotificationType.create(NotificationType.TYPES.SharedVaultItemRemoved).getValue(),
|
||||||
itemUuid: itemUuid,
|
itemUuid: dto.existingItem.uuid,
|
||||||
version: '1.0',
|
version: '1.0',
|
||||||
})
|
})
|
||||||
if (notificationPayloadOrError.isFailed()) {
|
if (notificationPayloadOrError.isFailed()) {
|
||||||
@@ -246,6 +248,15 @@ export class UpdateExistingItem implements UseCaseInterface<Item> {
|
|||||||
if (result.isFailed()) {
|
if (result.isFailed()) {
|
||||||
return Result.fail(result.getError())
|
return Result.fail(result.getError())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.domainEventPublisher.publish(
|
||||||
|
this.domainEventFactory.createItemRemovedFromSharedVaultEvent({
|
||||||
|
sharedVaultUuid: sharedVaultOperation.props.sharedVaultUuid.value,
|
||||||
|
itemUuid: dto.existingItem.uuid.value,
|
||||||
|
userUuid: userUuid.value,
|
||||||
|
roleNames: dto.roleNames,
|
||||||
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sharedVaultOperation && sharedVaultOperation.props.type === SharedVaultOperationOnItem.TYPES.AddToSharedVault) {
|
if (sharedVaultOperation && sharedVaultOperation.props.type === SharedVaultOperationOnItem.TYPES.AddToSharedVault) {
|
||||||
|
|||||||
+1
-1
@@ -65,7 +65,7 @@ export class BaseSharedVaultUsersController extends BaseHttpController {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
response.setHeader('x-invalidate-cache', response.locals.user.uuid)
|
response.setHeader('x-invalidate-cache', request.params.userUuid)
|
||||||
|
|
||||||
return this.json({
|
return this.json({
|
||||||
success: true,
|
success: true,
|
||||||
|
|||||||
@@ -155,15 +155,23 @@ export class MongoDBItemRepository implements ItemRepositoryInterface {
|
|||||||
|
|
||||||
async markItemsAsDeleted(itemUuids: string[], updatedAtTimestamp: number): Promise<void> {
|
async markItemsAsDeleted(itemUuids: string[], updatedAtTimestamp: number): Promise<void> {
|
||||||
await this.mongoRepository.updateMany(
|
await this.mongoRepository.updateMany(
|
||||||
{ where: { _id: { $in: itemUuids.map((uuid) => BSON.UUID.createFromHexString(uuid)) } } },
|
{ _id: { $in: itemUuids.map((uuid) => BSON.UUID.createFromHexString(uuid)) } },
|
||||||
{ deleted: true, content: null, encItemKey: null, authHash: null, updatedAtTimestamp },
|
{
|
||||||
|
$set: {
|
||||||
|
deleted: true,
|
||||||
|
content: null,
|
||||||
|
encItemKey: null,
|
||||||
|
authHash: null,
|
||||||
|
updatedAtTimestamp,
|
||||||
|
},
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateContentSize(itemUuid: string, contentSize: number): Promise<void> {
|
async updateContentSize(itemUuid: string, contentSize: number): Promise<void> {
|
||||||
await this.mongoRepository.updateOne(
|
await this.mongoRepository.updateOne(
|
||||||
{ where: { _id: { $eq: BSON.UUID.createFromHexString(itemUuid) } } },
|
{ _id: { $eq: BSON.UUID.createFromHexString(itemUuid) } },
|
||||||
{ contentSize },
|
{ $set: { contentSize } },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,18 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.10.36](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.10.35...@standardnotes/websockets-server@1.10.36) (2023-09-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/websockets-server
|
||||||
|
|
||||||
|
## [1.10.35](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.10.34...@standardnotes/websockets-server@1.10.35) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/websockets-server
|
||||||
|
|
||||||
|
## [1.10.34](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.10.33...@standardnotes/websockets-server@1.10.34) (2023-09-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/websockets-server
|
||||||
|
|
||||||
## [1.10.33](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.10.32...@standardnotes/websockets-server@1.10.33) (2023-09-06)
|
## [1.10.33](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.10.32...@standardnotes/websockets-server@1.10.33) (2023-09-06)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/websockets-server
|
**Note:** Version bump only for package @standardnotes/websockets-server
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/websockets-server",
|
"name": "@standardnotes/websockets-server",
|
||||||
"version": "1.10.33",
|
"version": "1.10.36",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user