Compare commits

...

28 Commits

Author SHA1 Message Date
standardci d1d6c753c4 chore(release): publish new version
- @standardnotes/analytics@2.26.6
 - @standardnotes/api-gateway@1.74.2
 - @standardnotes/auth-server@1.138.2
 - @standardnotes/domain-events-infra@1.12.23
 - @standardnotes/domain-events@2.124.0
 - @standardnotes/event-store@1.11.34
 - @standardnotes/files-server@1.22.13
 - @standardnotes/home-server@1.15.27
 - @standardnotes/revisions-server@1.33.0
 - @standardnotes/scheduler-server@1.20.38
 - @standardnotes/syncing-server@1.93.0
 - @standardnotes/websockets-server@1.10.35
2023-09-07 10:46:30 +00:00
Karol Sójko 3bd63f7674 feat: add removing revisions from shared vaults (#811) 2023-09-07 12:02:38 +02:00
standardci 376466d9b2 chore(release): publish new version
- @standardnotes/analytics@2.26.5
 - @standardnotes/api-gateway@1.74.1
 - @standardnotes/auth-server@1.138.1
 - @standardnotes/domain-core@1.28.0
 - @standardnotes/event-store@1.11.33
 - @standardnotes/files-server@1.22.12
 - @standardnotes/home-server@1.15.26
 - @standardnotes/revisions-server@1.32.0
 - @standardnotes/scheduler-server@1.20.37
 - @standardnotes/settings@1.21.30
 - @standardnotes/syncing-server@1.92.1
 - @standardnotes/websockets-server@1.10.34
2023-09-07 09:00:39 +00:00
Karol Sójko e100c52bbc feat(revisions): fetching single revision in shared vault (#810)
* feat(revisions): fetching single revision in shared vault

* fix(revisions): mapping to http representation
2023-09-07 10:23:03 +02:00
Aman Harwara d4830dec01 feat: add VaultsUser role name (#809)
* feat: add VaultsUser role name

* fix: test coverage
2023-09-07 08:07:06 +02:00
Karol Sójko 7e11821021 fix(revisions): query for shared vault revisions 2023-09-07 08:05:47 +02:00
standardci 4715e019a2 chore(release): publish new version
- @standardnotes/analytics@2.26.4
 - @standardnotes/api-gateway@1.74.0
 - @standardnotes/auth-server@1.138.0
 - @standardnotes/domain-core@1.27.0
 - @standardnotes/domain-events-infra@1.12.22
 - @standardnotes/domain-events@2.123.0
 - @standardnotes/event-store@1.11.32
 - @standardnotes/files-server@1.22.11
 - @standardnotes/home-server@1.15.25
 - @standardnotes/revisions-server@1.31.0
 - @standardnotes/scheduler-server@1.20.36
 - @standardnotes/security@1.13.0
 - @standardnotes/settings@1.21.29
 - @standardnotes/syncing-server@1.92.0
 - @standardnotes/websockets-server@1.10.33
2023-09-06 14:12:13 +00:00
Karol Sójko 794cd8734a feat: should be able to access shared item revisions as third party user (#807) 2023-09-06 15:36:23 +02:00
standardci 14d42b26bb chore(release): publish new version
- @standardnotes/websockets-server@1.10.32
2023-09-05 12:29:23 +00:00
Karol Sójko 6bb44afd91 fix(websockets): add missing region parameter in api gateway client 2023-09-05 13:50:30 +02:00
standardci c82345aeeb chore(release): publish new version
- @standardnotes/websockets-server@1.10.31
2023-09-05 06:49:48 +00:00
Karol Sójko 72ab08a0d0 fix(websockets): issue with sending messages to active websocket connections (#806) 2023-09-05 08:13:42 +02:00
standardci f2d1b47e40 chore(release): publish new version
- @standardnotes/home-server@1.15.24
 - @standardnotes/revisions-server@1.30.14
 - @standardnotes/syncing-server@1.91.3
2023-09-04 12:48:16 +00:00
Karol Sójko d9ee2c5be2 fix: prevent doubling transitions 2023-09-04 14:10:37 +02:00
standardci eb59902cf7 chore(release): publish new version
- @standardnotes/home-server@1.15.23
 - @standardnotes/revisions-server@1.30.13
 - @standardnotes/websockets-server@1.10.30
2023-09-04 11:11:04 +00:00
Karol Sójko 002074e4d1 fix(websockets): stringify response from the AWS Api Gateway 2023-09-04 12:32:47 +02:00
Karol Sójko 45b55068f9 fix(revisions): change logs severity in the transition process 2023-09-04 12:19:03 +02:00
Karol Sójko 157eee5d93 chore: increase mocha headless chrome global timeout 2023-09-04 12:06:49 +02:00
standardci d5f2b4f6eb chore(release): publish new version
- @standardnotes/home-server@1.15.22
 - @standardnotes/revisions-server@1.30.12
 - @standardnotes/websockets-server@1.10.29
2023-09-04 10:05:10 +00:00
Karol Sójko a7a93497e8 fix(revisions): change order field for transition of revisions 2023-09-04 10:56:14 +02:00
Karol Sójko 8f96f0ed7a fix(websockets): add response debug on websockets sending 2023-09-04 10:43:58 +02:00
standardci 3f064176f2 chore(release): publish new version
- @standardnotes/analytics@2.26.3
 - @standardnotes/api-gateway@1.73.7
 - @standardnotes/auth-server@1.137.6
 - @standardnotes/common@1.50.4
 - @standardnotes/domain-core@1.26.3
 - @standardnotes/domain-events-infra@1.12.21
 - @standardnotes/domain-events@2.122.2
 - @standardnotes/event-store@1.11.31
 - @standardnotes/files-server@1.22.10
 - @standardnotes/home-server@1.15.21
 - @standardnotes/predicates@1.6.11
 - @standardnotes/revisions-server@1.30.11
 - @standardnotes/scheduler-server@1.20.35
 - @standardnotes/security@1.12.2
 - @standardnotes/settings@1.21.28
 - @standardnotes/sncrypto-node@1.15.6
 - @standardnotes/syncing-server@1.91.2
 - @standardnotes/time@1.15.3
 - @standardnotes/websockets-server@1.10.28
2023-09-04 08:26:34 +00:00
Karol Sójko c7b0c7dfa8 fix(websockets): add debug logs 2023-09-04 09:47:20 +02:00
Karol Sójko df20dd46db fix(revisions): add more verbose logs to the transition 2023-09-04 09:05:54 +02:00
Karol Sójko 6dfd09989e chore: remove unused nodemon 2023-09-04 08:28:02 +02:00
Karol Sójko fc821709e2 chore: upgrade docker build push action: 2023-09-04 08:24:39 +02:00
Karol Sójko e986abaab5 chore: upgrade @types/uuid 2023-09-04 08:23:46 +02:00
Karol Sójko a006fb3119 chore: upgrade typescript eslint plugin 2023-09-04 08:22:42 +02:00
206 changed files with 3514 additions and 1022 deletions
+1 -1
View File
@@ -90,7 +90,7 @@ jobs:
uses: docker/setup-buildx-action@master
- name: Publish Docker image
uses: docker/build-push-action@v3
uses: docker/build-push-action@v4
with:
builder: ${{ steps.buildx.outputs.name }}
context: ${{ steps.bundle-dir.outputs.temp_dir }}
+2 -2
View File
@@ -57,7 +57,7 @@ jobs:
run: docker/is-available.sh http://localhost:3123 $(pwd)/logs
- name: Run E2E Test Suite
run: yarn dlx mocha-headless-chrome --timeout 1800000 -f http://localhost:9001/mocha/test.html
run: yarn dlx mocha-headless-chrome --timeout 3600000 -f http://localhost:9001/mocha/test.html
- name: Show logs on failure
if: ${{ failure() }}
@@ -162,7 +162,7 @@ jobs:
run: for i in {1..30}; do curl -s http://localhost:3123/healthcheck && break || sleep 1; done
- name: Run E2E Test Suite
run: yarn dlx mocha-headless-chrome --timeout 1800000 -f http://localhost:9001/mocha/test.html
run: yarn dlx mocha-headless-chrome --timeout 3600000 -f http://localhost:9001/mocha/test.html
- name: Show logs on failure
if: ${{ failure() }}
+1 -1
View File
@@ -35,7 +35,7 @@ jobs:
uses: docker/setup-buildx-action@master
- name: Publish Docker image
uses: docker/build-push-action@v3
uses: docker/build-push-action@v4
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
Generated
+418 -342
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+16
View File
@@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.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)
**Note:** Version bump only for package @standardnotes/analytics
## [2.26.3](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.26.2...@standardnotes/analytics@2.26.3) (2023-09-04)
**Note:** Version bump only for package @standardnotes/analytics
## [2.26.2](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.26.1...@standardnotes/analytics@2.26.2) (2023-09-01)
**Note:** Version bump only for package @standardnotes/analytics
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/analytics",
"version": "2.26.2",
"version": "2.26.6",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -29,7 +29,7 @@
"@types/jest": "^29.5.1",
"@types/mixpanel": "^2.14.4",
"@types/node": "^20.5.7",
"@typescript-eslint/eslint-plugin": "^5.59.2",
"@typescript-eslint/eslint-plugin": "^6.5.0",
"@typescript-eslint/parser": "^6.5.0",
"eslint": "^8.39.0",
"eslint-plugin-prettier": "^5.0.0",
+18
View File
@@ -3,6 +3,24 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [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)
### Features
* should be able to access shared item revisions as third party user ([#807](https://github.com/standardnotes/api-gateway/issues/807)) ([794cd87](https://github.com/standardnotes/api-gateway/commit/794cd8734acf89fb29f09dfb169a3f08f252bb6a))
## [1.73.7](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.73.6...@standardnotes/api-gateway@1.73.7) (2023-09-04)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.73.6](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.73.5...@standardnotes/api-gateway@1.73.6) (2023-09-01)
**Note:** Version bump only for package @standardnotes/api-gateway
+2 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api-gateway",
"version": "1.73.6",
"version": "1.74.2",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -54,12 +54,11 @@
"@types/jsonwebtoken": "^9.0.1",
"@types/node": "^20.5.7",
"@types/prettyjson": "^0.0.30",
"@typescript-eslint/eslint-plugin": "^5.59.2",
"@typescript-eslint/eslint-plugin": "^6.5.0",
"@typescript-eslint/parser": "^6.5.0",
"eslint": "^8.39.0",
"eslint-plugin-prettier": "^5.0.0",
"jest": "^29.5.0",
"nodemon": "^2.0.19",
"npm-check-updates": "^16.13.2",
"prettier": "^3.0.3",
"ts-jest": "^29.1.0",
@@ -72,6 +72,7 @@ export abstract class AuthMiddleware extends BaseMiddleware {
response.locals.session = decodedToken.session
response.locals.roles = decodedToken.roles
response.locals.sharedVaultOwnerContext = decodedToken.shared_vault_owner_context
response.locals.belongsToSharedVaults = decodedToken.belongs_to_shared_vaults ?? []
} catch (error) {
const errorMessage = (error as AxiosError).isAxiosError
? JSON.stringify((error as AxiosError).response?.data)
+18
View File
@@ -3,6 +3,24 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [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)
### Features
* should be able to access shared item revisions as third party user ([#807](https://github.com/standardnotes/server/issues/807)) ([794cd87](https://github.com/standardnotes/server/commit/794cd8734acf89fb29f09dfb169a3f08f252bb6a))
## [1.137.6](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.137.5...@standardnotes/auth-server@1.137.6) (2023-09-04)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.137.5](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.137.4...@standardnotes/auth-server@1.137.5) (2023-09-01)
**Note:** Version bump only for package @standardnotes/auth-server
@@ -0,0 +1,15 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class AddSharedVaultUsers1694000575425 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'CREATE TABLE `auth_shared_vault_users` (`uuid` varchar(36) NOT NULL, `shared_vault_uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `permission` varchar(24) NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `shared_vault_uuid_on_auth_shared_vault_users` (`shared_vault_uuid`), INDEX `user_uuid_on_auth_shared_vault_users` (`user_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
)
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP INDEX `user_uuid_on_auth_shared_vault_users` ON `auth_shared_vault_users`')
await queryRunner.query('DROP INDEX `shared_vault_uuid_on_auth_shared_vault_users` ON `auth_shared_vault_users`')
await queryRunner.query('DROP TABLE `auth_shared_vault_users`')
}
}
@@ -0,0 +1,21 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class AddSharedVaultUsers1694000640645 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'CREATE TABLE "auth_shared_vault_users" ("uuid" varchar PRIMARY KEY NOT NULL, "shared_vault_uuid" varchar(36) NOT NULL, "user_uuid" varchar(36) NOT NULL, "permission" varchar(24) NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
)
await queryRunner.query(
'CREATE INDEX "shared_vault_uuid_on_auth_shared_vault_users" ON "auth_shared_vault_users" ("shared_vault_uuid") ',
)
await queryRunner.query(
'CREATE INDEX "user_uuid_on_auth_shared_vault_users" ON "auth_shared_vault_users" ("user_uuid") ',
)
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP INDEX "user_uuid_on_auth_shared_vault_users"')
await queryRunner.query('DROP INDEX "shared_vault_uuid_on_auth_shared_vault_users"')
await queryRunner.query('DROP TABLE "auth_shared_vault_users"')
}
}
+3 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/auth-server",
"version": "1.137.5",
"version": "1.138.2",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -84,13 +84,12 @@
"@types/otplib": "^10.0.0",
"@types/prettyjson": "^0.0.30",
"@types/ua-parser-js": "^0.7.36",
"@types/uuid": "^9.0.2",
"@typescript-eslint/eslint-plugin": "^5.59.2",
"@types/uuid": "^9.0.3",
"@typescript-eslint/eslint-plugin": "^6.5.0",
"@typescript-eslint/parser": "^6.5.0",
"eslint": "^8.39.0",
"eslint-plugin-prettier": "^5.0.0",
"jest": "^29.5.0",
"nodemon": "^2.0.19",
"npm-check-updates": "^16.13.2",
"prettier": "^3.0.3",
"ts-jest": "^29.1.0",
+55
View File
@@ -189,6 +189,7 @@ import {
ControllerContainer,
ControllerContainerInterface,
MapperInterface,
SharedVaultUser,
} from '@standardnotes/domain-core'
import { SessionTracePersistenceMapper } from '../Mapping/SessionTracePersistenceMapper'
import { SessionTrace } from '../Domain/Session/SessionTrace'
@@ -263,6 +264,14 @@ import { InMemoryTransitionStatusRepository } from '../Infra/InMemory/InMemoryTr
import { TransitionStatusUpdatedEventHandler } from '../Domain/Handler/TransitionStatusUpdatedEventHandler'
import { UpdateTransitionStatus } from '../Domain/UseCase/UpdateTransitionStatus/UpdateTransitionStatus'
import { GetTransitionStatus } from '../Domain/UseCase/GetTransitionStatus/GetTransitionStatus'
import { TypeORMSharedVaultUser } from '../Infra/TypeORM/TypeORMSharedVaultUser'
import { SharedVaultUserPersistenceMapper } from '../Mapping/SharedVaultUserPersistenceMapper'
import { SharedVaultUserRepositoryInterface } from '../Domain/SharedVault/SharedVaultUserRepositoryInterface'
import { TypeORMSharedVaultUserRepository } from '../Infra/TypeORM/TypeORMSharedVaultUserRepository'
import { AddSharedVaultUser } from '../Domain/UseCase/AddSharedVaultUser/AddSharedVaultUser'
import { RemoveSharedVaultUser } from '../Domain/UseCase/RemoveSharedVaultUser/RemoveSharedVaultUser'
import { UserAddedToSharedVaultEventHandler } from '../Domain/Handler/UserAddedToSharedVaultEventHandler'
import { UserRemovedFromSharedVaultEventHandler } from '../Domain/Handler/UserRemovedFromSharedVaultEventHandler'
export class ContainerConfigLoader {
async load(configuration?: {
@@ -372,6 +381,9 @@ export class ContainerConfigLoader {
container
.bind<MapperInterface<CacheEntry, TypeORMCacheEntry>>(TYPES.Auth_CacheEntryPersistenceMapper)
.toConstantValue(new CacheEntryPersistenceMapper())
container
.bind<MapperInterface<SharedVaultUser, TypeORMSharedVaultUser>>(TYPES.Auth_SharedVaultUserPersistenceMapper)
.toConstantValue(new SharedVaultUserPersistenceMapper())
// ORM
container
@@ -412,6 +424,9 @@ export class ContainerConfigLoader {
container
.bind<Repository<TypeORMCacheEntry>>(TYPES.Auth_ORMCacheEntryRepository)
.toConstantValue(appDataSource.getRepository(TypeORMCacheEntry))
container
.bind<Repository<TypeORMSharedVaultUser>>(TYPES.Auth_ORMSharedVaultUserRepository)
.toConstantValue(appDataSource.getRepository(TypeORMSharedVaultUser))
// Repositories
container.bind<SessionRepositoryInterface>(TYPES.Auth_SessionRepository).to(TypeORMSessionRepository)
@@ -468,6 +483,16 @@ export class ContainerConfigLoader {
container.get(TYPES.Auth_CacheEntryPersistenceMapper),
),
)
container
.bind<SharedVaultUserRepositoryInterface>(TYPES.Auth_SharedVaultUserRepository)
.toConstantValue(
new TypeORMSharedVaultUserRepository(
container.get<Repository<TypeORMSharedVaultUser>>(TYPES.Auth_ORMSharedVaultUserRepository),
container.get<MapperInterface<SharedVaultUser, TypeORMSharedVaultUser>>(
TYPES.Auth_SharedVaultUserPersistenceMapper,
),
),
)
// Middleware
container.bind<SessionMiddleware>(TYPES.Auth_SessionMiddleware).to(SessionMiddleware)
@@ -926,6 +951,18 @@ export class ContainerConfigLoader {
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
),
)
container
.bind<AddSharedVaultUser>(TYPES.Auth_AddSharedVaultUser)
.toConstantValue(
new AddSharedVaultUser(container.get<SharedVaultUserRepositoryInterface>(TYPES.Auth_SharedVaultUserRepository)),
)
container
.bind<RemoveSharedVaultUser>(TYPES.Auth_RemoveSharedVaultUser)
.toConstantValue(
new RemoveSharedVaultUser(
container.get<SharedVaultUserRepositoryInterface>(TYPES.Auth_SharedVaultUserRepository),
),
)
// Controller
container
@@ -1075,6 +1112,22 @@ export class ContainerConfigLoader {
container.get<winston.Logger>(TYPES.Auth_Logger),
),
)
container
.bind<UserAddedToSharedVaultEventHandler>(TYPES.Auth_UserAddedToSharedVaultEventHandler)
.toConstantValue(
new UserAddedToSharedVaultEventHandler(
container.get<AddSharedVaultUser>(TYPES.Auth_AddSharedVaultUser),
container.get<winston.Logger>(TYPES.Auth_Logger),
),
)
container
.bind<UserRemovedFromSharedVaultEventHandler>(TYPES.Auth_UserRemovedFromSharedVaultEventHandler)
.toConstantValue(
new UserRemovedFromSharedVaultEventHandler(
container.get<RemoveSharedVaultUser>(TYPES.Auth_RemoveSharedVaultUser),
container.get<winston.Logger>(TYPES.Auth_Logger),
),
)
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
['USER_REGISTERED', container.get(TYPES.Auth_UserRegisteredEventHandler)],
@@ -1107,6 +1160,8 @@ export class ContainerConfigLoader {
['EMAIL_SUBSCRIPTION_UNSUBSCRIBED', container.get(TYPES.Auth_EmailSubscriptionUnsubscribedEventHandler)],
['PAYMENTS_ACCOUNT_DELETED', container.get(TYPES.Auth_PaymentsAccountDeletedEventHandler)],
['TRANSITION_STATUS_UPDATED', container.get(TYPES.Auth_TransitionStatusUpdatedEventHandler)],
['USER_ADDED_TO_SHARED_VAULT', container.get(TYPES.Auth_UserAddedToSharedVaultEventHandler)],
['USER_REMOVED_FROM_SHARED_VAULT', container.get(TYPES.Auth_UserRemovedFromSharedVaultEventHandler)],
])
if (isConfiguredForHomeServer) {
@@ -18,6 +18,7 @@ import { TypeORMEmergencyAccessInvitation } from '../Infra/TypeORM/TypeORMEmerge
import { TypeORMSessionTrace } from '../Infra/TypeORM/TypeORMSessionTrace'
import { Env } from './Env'
import { SqliteConnectionOptions } from 'typeorm/driver/sqlite/SqliteConnectionOptions'
import { TypeORMSharedVaultUser } from '../Infra/TypeORM/TypeORMSharedVaultUser'
export class AppDataSource {
private _dataSource: DataSource | undefined
@@ -64,6 +65,7 @@ export class AppDataSource {
TypeORMAuthenticatorChallenge,
TypeORMEmergencyAccessInvitation,
TypeORMCacheEntry,
TypeORMSharedVaultUser,
],
migrations: [`${__dirname}/../../migrations/${isConfiguredForMySQL ? 'mysql' : 'sqlite'}/*.js`],
migrationsRun: true,
+7
View File
@@ -9,6 +9,7 @@ const TYPES = {
Auth_AuthenticatorPersistenceMapper: Symbol.for('Auth_AuthenticatorPersistenceMapper'),
Auth_AuthenticatorHttpMapper: Symbol.for('Auth_AuthenticatorHttpMapper'),
Auth_CacheEntryPersistenceMapper: Symbol.for('Auth_CacheEntryPersistenceMapper'),
Auth_SharedVaultUserPersistenceMapper: Symbol.for('Auth_SharedVaultUserPersistenceMapper'),
// Controller
Auth_ControllerContainer: Symbol.for('Auth_ControllerContainer'),
Auth_AuthController: Symbol.for('Auth_AuthController'),
@@ -36,6 +37,7 @@ const TYPES = {
Auth_AuthenticatorChallengeRepository: Symbol.for('Auth_AuthenticatorChallengeRepository'),
Auth_CacheEntryRepository: Symbol.for('Auth_CacheEntryRepository'),
Auth_TransitionStatusRepository: Symbol.for('Auth_TransitionStatusRepository'),
Auth_SharedVaultUserRepository: Symbol.for('Auth_SharedVaultUserRepository'),
// ORM
Auth_ORMOfflineSettingRepository: Symbol.for('Auth_ORMOfflineSettingRepository'),
Auth_ORMOfflineUserSubscriptionRepository: Symbol.for('Auth_ORMOfflineUserSubscriptionRepository'),
@@ -51,6 +53,7 @@ const TYPES = {
Auth_ORMAuthenticatorRepository: Symbol.for('Auth_ORMAuthenticatorRepository'),
Auth_ORMAuthenticatorChallengeRepository: Symbol.for('Auth_ORMAuthenticatorChallengeRepository'),
Auth_ORMCacheEntryRepository: Symbol.for('Auth_ORMCacheEntryRepository'),
Auth_ORMSharedVaultUserRepository: Symbol.for('Auth_ORMSharedVaultUserRepository'),
// Middleware
Auth_RequiredCrossServiceTokenMiddleware: Symbol.for('Auth_RequiredCrossServiceTokenMiddleware'),
Auth_OptionalCrossServiceTokenMiddleware: Symbol.for('Auth_OptionalCrossServiceTokenMiddleware'),
@@ -157,6 +160,8 @@ const TYPES = {
Auth_UpdateStorageQuotaUsedForUser: Symbol.for('Auth_UpdateStorageQuotaUsedForUser'),
Auth_UpdateTransitionStatus: Symbol.for('Auth_UpdateTransitionStatus'),
Auth_GetTransitionStatus: Symbol.for('Auth_GetTransitionStatus'),
Auth_AddSharedVaultUser: Symbol.for('Auth_AddSharedVaultUser'),
Auth_RemoveSharedVaultUser: Symbol.for('Auth_RemoveSharedVaultUser'),
// Handlers
Auth_UserRegisteredEventHandler: Symbol.for('Auth_UserRegisteredEventHandler'),
Auth_AccountDeletionRequestedEventHandler: Symbol.for('Auth_AccountDeletionRequestedEventHandler'),
@@ -186,6 +191,8 @@ const TYPES = {
Auth_EmailSubscriptionUnsubscribedEventHandler: Symbol.for('Auth_EmailSubscriptionUnsubscribedEventHandler'),
Auth_PaymentsAccountDeletedEventHandler: Symbol.for('Auth_PaymentsAccountDeletedEventHandler'),
Auth_TransitionStatusUpdatedEventHandler: Symbol.for('Auth_TransitionStatusUpdatedEventHandler'),
Auth_UserAddedToSharedVaultEventHandler: Symbol.for('Auth_UserAddedToSharedVaultEventHandler'),
Auth_UserRemovedFromSharedVaultEventHandler: Symbol.for('Auth_UserRemovedFromSharedVaultEventHandler'),
// Services
Auth_DeviceDetector: Symbol.for('Auth_DeviceDetector'),
Auth_SessionService: Symbol.for('Auth_SessionService'),
@@ -0,0 +1,24 @@
import { DomainEventHandlerInterface, UserAddedToSharedVaultEvent } from '@standardnotes/domain-events'
import { Logger } from 'winston'
import { AddSharedVaultUser } from '../UseCase/AddSharedVaultUser/AddSharedVaultUser'
export class UserAddedToSharedVaultEventHandler implements DomainEventHandlerInterface {
constructor(
private addSharedVaultUser: AddSharedVaultUser,
private logger: Logger,
) {}
async handle(event: UserAddedToSharedVaultEvent): Promise<void> {
const result = await this.addSharedVaultUser.execute({
userUuid: event.payload.userUuid,
sharedVaultUuid: event.payload.sharedVaultUuid,
permission: event.payload.permission,
createdAt: event.payload.createdAt,
updatedAt: event.payload.updatedAt,
})
if (result.isFailed()) {
this.logger.error(`Failed to add user to shared vault: ${result.getError()}`)
}
}
}
@@ -0,0 +1,22 @@
import { DomainEventHandlerInterface, UserRemovedFromSharedVaultEvent } from '@standardnotes/domain-events'
import { Logger } from 'winston'
import { RemoveSharedVaultUser } from '../UseCase/RemoveSharedVaultUser/RemoveSharedVaultUser'
export class UserRemovedFromSharedVaultEventHandler implements DomainEventHandlerInterface {
constructor(
private removeSharedVaultUser: RemoveSharedVaultUser,
private logger: Logger,
) {}
async handle(event: UserRemovedFromSharedVaultEvent): Promise<void> {
const result = await this.removeSharedVaultUser.execute({
userUuid: event.payload.userUuid,
sharedVaultUuid: event.payload.sharedVaultUuid,
})
if (result.isFailed()) {
this.logger.error(`Failed to remove user from shared vault: ${result.getError()}`)
}
}
}
@@ -0,0 +1,8 @@
import { SharedVaultUser, Uuid } from '@standardnotes/domain-core'
export interface SharedVaultUserRepositoryInterface {
findByUserUuidAndSharedVaultUuid(dto: { userUuid: Uuid; sharedVaultUuid: Uuid }): Promise<SharedVaultUser | null>
findByUserUuid(userUuid: Uuid): Promise<SharedVaultUser[]>
save(sharedVaultUser: SharedVaultUser): Promise<void>
remove(sharedVault: SharedVaultUser): Promise<void>
}
@@ -0,0 +1,106 @@
import { Result, SharedVaultUser } from '@standardnotes/domain-core'
import { SharedVaultUserRepositoryInterface } from '../../SharedVault/SharedVaultUserRepositoryInterface'
import { AddSharedVaultUser } from './AddSharedVaultUser'
describe('AddSharedVaultUser', () => {
let sharedVaultUserRepository: SharedVaultUserRepositoryInterface
const createUseCase = () => new AddSharedVaultUser(sharedVaultUserRepository)
beforeEach(() => {
sharedVaultUserRepository = {} as jest.Mocked<SharedVaultUserRepositoryInterface>
sharedVaultUserRepository.save = jest.fn()
})
it('should save shared vault user', async () => {
const useCase = createUseCase()
const result = await useCase.execute({
userUuid: '00000000-0000-0000-0000-000000000000',
sharedVaultUuid: '00000000-0000-0000-0000-000000000000',
permission: 'read',
createdAt: 1,
updatedAt: 2,
})
expect(result.isFailed()).toBeFalsy()
expect(sharedVaultUserRepository.save).toHaveBeenCalled()
})
it('should fail when user uuid is invalid', async () => {
const useCase = createUseCase()
const result = await useCase.execute({
userUuid: 'invalid',
sharedVaultUuid: '00000000-0000-0000-0000-000000000000',
permission: 'read',
createdAt: 1,
updatedAt: 2,
})
expect(result.isFailed()).toBeTruthy()
expect(sharedVaultUserRepository.save).not.toHaveBeenCalled()
})
it('should fail when shared vault uuid is invalid', async () => {
const useCase = createUseCase()
const result = await useCase.execute({
userUuid: '00000000-0000-0000-0000-000000000000',
sharedVaultUuid: 'invalid',
permission: 'read',
createdAt: 1,
updatedAt: 2,
})
expect(result.isFailed()).toBeTruthy()
expect(sharedVaultUserRepository.save).not.toHaveBeenCalled()
})
it('should fail when permission is invalid', async () => {
const useCase = createUseCase()
const result = await useCase.execute({
userUuid: '00000000-0000-0000-0000-000000000000',
sharedVaultUuid: '00000000-0000-0000-0000-000000000000',
permission: 'invalid',
createdAt: 1,
updatedAt: 2,
})
expect(result.isFailed()).toBeTruthy()
expect(sharedVaultUserRepository.save).not.toHaveBeenCalled()
})
it('should fail when timestamps are invalid', async () => {
const useCase = createUseCase()
const result = await useCase.execute({
userUuid: '00000000-0000-0000-0000-000000000000',
sharedVaultUuid: '00000000-0000-0000-0000-000000000000',
permission: 'read',
createdAt: 'invalid' as unknown as number,
updatedAt: 1,
})
expect(result.isFailed()).toBeTruthy()
expect(sharedVaultUserRepository.save).not.toHaveBeenCalled()
})
it('should fail when shared vault user is invalid', async () => {
const mock = jest.spyOn(SharedVaultUser, 'create')
mock.mockReturnValue(Result.fail('Oops'))
const result = await createUseCase().execute({
userUuid: '00000000-0000-0000-0000-000000000000',
sharedVaultUuid: '00000000-0000-0000-0000-000000000000',
permission: 'read',
createdAt: 2,
updatedAt: 1,
})
expect(result.isFailed()).toBeTruthy()
mock.mockRestore()
})
})
@@ -0,0 +1,56 @@
import {
Result,
SharedVaultUser,
SharedVaultUserPermission,
Timestamps,
UseCaseInterface,
Uuid,
} from '@standardnotes/domain-core'
import { SharedVaultUserRepositoryInterface } from '../../SharedVault/SharedVaultUserRepositoryInterface'
import { AddSharedVaultUserDTO } from './AddSharedVaultUserDTO'
export class AddSharedVaultUser implements UseCaseInterface<void> {
constructor(private sharedVaultUserRepository: SharedVaultUserRepositoryInterface) {}
async execute(dto: AddSharedVaultUserDTO): Promise<Result<void>> {
const userUuidOrError = Uuid.create(dto.userUuid)
if (userUuidOrError.isFailed()) {
return Result.fail(userUuidOrError.getError())
}
const userUuid = userUuidOrError.getValue()
const sharedVaultUuidOrError = Uuid.create(dto.sharedVaultUuid)
if (sharedVaultUuidOrError.isFailed()) {
return Result.fail(sharedVaultUuidOrError.getError())
}
const sharedVaultUuid = sharedVaultUuidOrError.getValue()
const permissionOrError = SharedVaultUserPermission.create(dto.permission)
if (permissionOrError.isFailed()) {
return Result.fail(permissionOrError.getError())
}
const permission = permissionOrError.getValue()
const timestampsOrError = Timestamps.create(dto.createdAt, dto.updatedAt)
if (timestampsOrError.isFailed()) {
return Result.fail(timestampsOrError.getError())
}
const timestamps = timestampsOrError.getValue()
const sharedVaultUserOrError = SharedVaultUser.create({
userUuid,
sharedVaultUuid,
permission,
timestamps,
})
if (sharedVaultUserOrError.isFailed()) {
return Result.fail(sharedVaultUserOrError.getError())
}
const sharedVaultUser = sharedVaultUserOrError.getValue()
await this.sharedVaultUserRepository.save(sharedVaultUser)
return Result.ok()
}
}
@@ -0,0 +1,7 @@
export interface AddSharedVaultUserDTO {
sharedVaultUuid: string
userUuid: string
permission: string
createdAt: number
updatedAt: number
}
@@ -9,8 +9,9 @@ import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
import { CreateCrossServiceToken } from './CreateCrossServiceToken'
import { GetSetting } from '../GetSetting/GetSetting'
import { Result } from '@standardnotes/domain-core'
import { Result, SharedVaultUser, SharedVaultUserPermission, Timestamps, Uuid } from '@standardnotes/domain-core'
import { TransitionStatusRepositoryInterface } from '../../Transition/TransitionStatusRepositoryInterface'
import { SharedVaultUserRepositoryInterface } from '../../SharedVault/SharedVaultUserRepositoryInterface'
describe('CreateCrossServiceToken', () => {
let userProjector: ProjectorInterface<User>
@@ -20,6 +21,7 @@ describe('CreateCrossServiceToken', () => {
let userRepository: UserRepositoryInterface
let getSettingUseCase: GetSetting
let transitionStatusRepository: TransitionStatusRepositoryInterface
let sharedVaultUserRepository: SharedVaultUserRepositoryInterface
const jwtTTL = 60
let session: Session
@@ -36,6 +38,7 @@ describe('CreateCrossServiceToken', () => {
jwtTTL,
getSettingUseCase,
transitionStatusRepository,
sharedVaultUserRepository,
)
beforeEach(() => {
@@ -70,6 +73,16 @@ describe('CreateCrossServiceToken', () => {
transitionStatusRepository = {} as jest.Mocked<TransitionStatusRepositoryInterface>
transitionStatusRepository.getStatus = jest.fn().mockReturnValue('TO-DO')
sharedVaultUserRepository = {} as jest.Mocked<SharedVaultUserRepositoryInterface>
sharedVaultUserRepository.findByUserUuid = jest.fn().mockReturnValue([
SharedVaultUser.create({
permission: SharedVaultUserPermission.create('read').getValue(),
sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
timestamps: Timestamps.create(123456789, 123456789).getValue(),
userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
}).getValue(),
])
})
it('should create a cross service token for user', async () => {
@@ -86,6 +99,12 @@ describe('CreateCrossServiceToken', () => {
uuid: '1-3-4',
},
],
belongs_to_shared_vaults: [
{
shared_vault_uuid: '00000000-0000-0000-0000-000000000000',
permission: 'read',
},
],
session: {
test: 'test',
},
@@ -115,6 +134,12 @@ describe('CreateCrossServiceToken', () => {
uuid: '1-3-4',
},
],
belongs_to_shared_vaults: [
{
shared_vault_uuid: '00000000-0000-0000-0000-000000000000',
permission: 'read',
},
],
session: {
test: 'test',
},
@@ -141,6 +166,12 @@ describe('CreateCrossServiceToken', () => {
uuid: '1-3-4',
},
],
belongs_to_shared_vaults: [
{
shared_vault_uuid: '00000000-0000-0000-0000-000000000000',
permission: 'read',
},
],
user: {
email: 'test@test.te',
uuid: '00000000-0000-0000-0000-000000000000',
@@ -164,6 +195,12 @@ describe('CreateCrossServiceToken', () => {
uuid: '1-3-4',
},
],
belongs_to_shared_vaults: [
{
shared_vault_uuid: '00000000-0000-0000-0000-000000000000',
permission: 'read',
},
],
user: {
email: 'test@test.te',
uuid: '00000000-0000-0000-0000-000000000000',
@@ -208,6 +245,12 @@ describe('CreateCrossServiceToken', () => {
uuid: '1-3-4',
},
],
belongs_to_shared_vaults: [
{
shared_vault_uuid: '00000000-0000-0000-0000-000000000000',
permission: 'read',
},
],
session: {
test: 'test',
},
@@ -13,6 +13,7 @@ import { CreateCrossServiceTokenDTO } from './CreateCrossServiceTokenDTO'
import { GetSetting } from '../GetSetting/GetSetting'
import { SettingName } from '@standardnotes/settings'
import { TransitionStatusRepositoryInterface } from '../../Transition/TransitionStatusRepositoryInterface'
import { SharedVaultUserRepositoryInterface } from '../../SharedVault/SharedVaultUserRepositoryInterface'
@injectable()
export class CreateCrossServiceToken implements UseCaseInterface<string> {
@@ -27,6 +28,7 @@ export class CreateCrossServiceToken implements UseCaseInterface<string> {
private getSettingUseCase: GetSetting,
@inject(TYPES.Auth_TransitionStatusRepository)
private transitionStatusRepository: TransitionStatusRepositoryInterface,
@inject(TYPES.Auth_SharedVaultUserRepository) private sharedVaultUserRepository: SharedVaultUserRepositoryInterface,
) {}
async execute(dto: CreateCrossServiceTokenDTO): Promise<Result<string>> {
@@ -49,11 +51,19 @@ export class CreateCrossServiceToken implements UseCaseInterface<string> {
const roles = await user.roles
const sharedVaultAssociations = await this.sharedVaultUserRepository.findByUserUuid(
Uuid.create(user.uuid).getValue(),
)
const authTokenData: CrossServiceTokenData = {
user: this.projectUser(user),
roles: this.projectRoles(roles),
shared_vault_owner_context: undefined,
ongoing_transition: transitionStatus === 'STARTED',
belongs_to_shared_vaults: sharedVaultAssociations.map((association) => ({
shared_vault_uuid: association.props.sharedVaultUuid.value,
permission: association.props.permission.value,
})),
}
if (dto.sharedVaultOwnerContext !== undefined) {
@@ -0,0 +1,68 @@
import { SharedVaultUser } from '@standardnotes/domain-core'
import { SharedVaultUserRepositoryInterface } from '../../SharedVault/SharedVaultUserRepositoryInterface'
import { RemoveSharedVaultUser } from './RemoveSharedVaultUser'
describe('RemoveSharedVaultUser', () => {
let sharedVaultUserRepository: SharedVaultUserRepositoryInterface
const createUseCase = () => new RemoveSharedVaultUser(sharedVaultUserRepository)
beforeEach(() => {
sharedVaultUserRepository = {} as jest.Mocked<SharedVaultUserRepositoryInterface>
sharedVaultUserRepository.findByUserUuidAndSharedVaultUuid = jest
.fn()
.mockReturnValue({} as jest.Mocked<SharedVaultUser>)
sharedVaultUserRepository.remove = jest.fn()
})
it('should remove shared vault user', async () => {
const useCase = createUseCase()
const result = await useCase.execute({
userUuid: '00000000-0000-0000-0000-000000000000',
sharedVaultUuid: '00000000-0000-0000-0000-000000000000',
})
expect(result.isFailed()).toBeFalsy()
expect(sharedVaultUserRepository.remove).toHaveBeenCalled()
})
it('should fail when user uuid is invalid', async () => {
const useCase = createUseCase()
const result = await useCase.execute({
userUuid: 'invalid',
sharedVaultUuid: '00000000-0000-0000-0000-000000000000',
})
expect(result.isFailed()).toBeTruthy()
expect(sharedVaultUserRepository.remove).not.toHaveBeenCalled()
})
it('should fail when shared vault uuid is invalid', async () => {
const useCase = createUseCase()
const result = await useCase.execute({
userUuid: '00000000-0000-0000-0000-000000000000',
sharedVaultUuid: 'invalid',
})
expect(result.isFailed()).toBeTruthy()
expect(sharedVaultUserRepository.remove).not.toHaveBeenCalled()
})
it('should fail when shared vault user is not found', async () => {
sharedVaultUserRepository.findByUserUuidAndSharedVaultUuid = jest.fn().mockReturnValue(null)
const useCase = createUseCase()
const result = await useCase.execute({
userUuid: '00000000-0000-0000-0000-000000000000',
sharedVaultUuid: '00000000-0000-0000-0000-000000000000',
})
expect(result.isFailed()).toBeTruthy()
expect(sharedVaultUserRepository.remove).not.toHaveBeenCalled()
})
})
@@ -0,0 +1,34 @@
import { Result, UseCaseInterface, Uuid } from '@standardnotes/domain-core'
import { SharedVaultUserRepositoryInterface } from '../../SharedVault/SharedVaultUserRepositoryInterface'
import { RemoveSharedVaultUserDTO } from './RemoveSharedVaultUserDTO'
export class RemoveSharedVaultUser implements UseCaseInterface<void> {
constructor(private sharedVaultUserRepository: SharedVaultUserRepositoryInterface) {}
async execute(dto: RemoveSharedVaultUserDTO): Promise<Result<void>> {
const userUuidOrError = Uuid.create(dto.userUuid)
if (userUuidOrError.isFailed()) {
return Result.fail(userUuidOrError.getError())
}
const userUuid = userUuidOrError.getValue()
const sharedVaultUuidOrError = Uuid.create(dto.sharedVaultUuid)
if (sharedVaultUuidOrError.isFailed()) {
return Result.fail(sharedVaultUuidOrError.getError())
}
const sharedVaultUuid = sharedVaultUuidOrError.getValue()
const sharedVaultUser = await this.sharedVaultUserRepository.findByUserUuidAndSharedVaultUuid({
userUuid,
sharedVaultUuid,
})
if (!sharedVaultUser) {
return Result.fail('Shared vault user not found')
}
await this.sharedVaultUserRepository.remove(sharedVaultUser)
return Result.ok()
}
}
@@ -0,0 +1,4 @@
export interface RemoveSharedVaultUserDTO {
sharedVaultUuid: string
userUuid: string
}
@@ -0,0 +1,40 @@
import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'
@Entity({ name: 'auth_shared_vault_users' })
export class TypeORMSharedVaultUser {
@PrimaryGeneratedColumn('uuid')
declare uuid: string
@Column({
name: 'shared_vault_uuid',
length: 36,
})
@Index('shared_vault_uuid_on_auth_shared_vault_users')
declare sharedVaultUuid: string
@Column({
name: 'user_uuid',
length: 36,
})
@Index('user_uuid_on_auth_shared_vault_users')
declare userUuid: string
@Column({
name: 'permission',
type: 'varchar',
length: 24,
})
declare permission: string
@Column({
name: 'created_at_timestamp',
type: 'bigint',
})
declare createdAtTimestamp: number
@Column({
name: 'updated_at_timestamp',
type: 'bigint',
})
declare updatedAtTimestamp: number
}
@@ -0,0 +1,54 @@
import { Repository } from 'typeorm'
import { MapperInterface, SharedVaultUser, Uuid } from '@standardnotes/domain-core'
import { SharedVaultUserRepositoryInterface } from '../../Domain/SharedVault/SharedVaultUserRepositoryInterface'
import { TypeORMSharedVaultUser } from './TypeORMSharedVaultUser'
export class TypeORMSharedVaultUserRepository implements SharedVaultUserRepositoryInterface {
constructor(
private ormRepository: Repository<TypeORMSharedVaultUser>,
private mapper: MapperInterface<SharedVaultUser, TypeORMSharedVaultUser>,
) {}
async findByUserUuid(userUuid: Uuid): Promise<SharedVaultUser[]> {
const persistence = await this.ormRepository
.createQueryBuilder('shared_vault_user')
.where('shared_vault_user.user_uuid = :userUuid', {
userUuid: userUuid.value,
})
.getMany()
return persistence.map((p) => this.mapper.toDomain(p))
}
async findByUserUuidAndSharedVaultUuid(dto: {
userUuid: Uuid
sharedVaultUuid: Uuid
}): Promise<SharedVaultUser | null> {
const persistence = await this.ormRepository
.createQueryBuilder('shared_vault_user')
.where('shared_vault_user.user_uuid = :userUuid', {
userUuid: dto.userUuid.value,
})
.andWhere('shared_vault_user.shared_vault_uuid = :sharedVaultUuid', {
sharedVaultUuid: dto.sharedVaultUuid.value,
})
.getOne()
if (persistence === null) {
return null
}
return this.mapper.toDomain(persistence)
}
async save(sharedVaultUser: SharedVaultUser): Promise<void> {
const persistence = this.mapper.toProjection(sharedVaultUser)
await this.ormRepository.save(persistence)
}
async remove(sharedVaultUser: SharedVaultUser): Promise<void> {
await this.ormRepository.remove(this.mapper.toProjection(sharedVaultUser))
}
}
@@ -0,0 +1,67 @@
import {
Timestamps,
MapperInterface,
UniqueEntityId,
Uuid,
SharedVaultUserPermission,
SharedVaultUser,
} from '@standardnotes/domain-core'
import { TypeORMSharedVaultUser } from '../Infra/TypeORM/TypeORMSharedVaultUser'
export class SharedVaultUserPersistenceMapper implements MapperInterface<SharedVaultUser, TypeORMSharedVaultUser> {
toDomain(projection: TypeORMSharedVaultUser): SharedVaultUser {
const userUuidOrError = Uuid.create(projection.userUuid)
if (userUuidOrError.isFailed()) {
throw new Error(`Failed to create shared vault user from projection: ${userUuidOrError.getError()}`)
}
const userUuid = userUuidOrError.getValue()
const sharedVaultUuidOrError = Uuid.create(projection.sharedVaultUuid)
if (sharedVaultUuidOrError.isFailed()) {
throw new Error(`Failed to create shared vault user from projection: ${sharedVaultUuidOrError.getError()}`)
}
const sharedVaultUuid = sharedVaultUuidOrError.getValue()
const timestampsOrError = Timestamps.create(projection.createdAtTimestamp, projection.updatedAtTimestamp)
if (timestampsOrError.isFailed()) {
throw new Error(`Failed to create shared vault user from projection: ${timestampsOrError.getError()}`)
}
const timestamps = timestampsOrError.getValue()
const permissionOrError = SharedVaultUserPermission.create(projection.permission)
if (permissionOrError.isFailed()) {
throw new Error(`Failed to create shared vault user from projection: ${permissionOrError.getError()}`)
}
const permission = permissionOrError.getValue()
const sharedVaultUserOrError = SharedVaultUser.create(
{
userUuid,
sharedVaultUuid,
permission,
timestamps,
},
new UniqueEntityId(projection.uuid),
)
if (sharedVaultUserOrError.isFailed()) {
throw new Error(`Failed to create shared vault user from projection: ${sharedVaultUserOrError.getError()}`)
}
const sharedVaultUser = sharedVaultUserOrError.getValue()
return sharedVaultUser
}
toProjection(domain: SharedVaultUser): TypeORMSharedVaultUser {
const typeorm = new TypeORMSharedVaultUser()
typeorm.uuid = domain.id.toString()
typeorm.sharedVaultUuid = domain.props.sharedVaultUuid.value
typeorm.userUuid = domain.props.userUuid.value
typeorm.permission = domain.props.permission.value
typeorm.createdAtTimestamp = domain.props.timestamps.createdAt
typeorm.updatedAtTimestamp = domain.props.timestamps.updatedAt
return typeorm
}
}
+4
View File
@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.50.4](https://github.com/standardnotes/server/compare/@standardnotes/common@1.50.3...@standardnotes/common@1.50.4) (2023-09-04)
**Note:** Version bump only for package @standardnotes/common
## [1.50.3](https://github.com/standardnotes/server/compare/@standardnotes/common@1.50.2...@standardnotes/common@1.50.3) (2023-09-01)
**Note:** Version bump only for package @standardnotes/common
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/common",
"version": "1.50.3",
"version": "1.50.4",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -25,7 +25,7 @@
"devDependencies": {
"@types/jest": "^29.5.1",
"@types/node": "^20.5.7",
"@typescript-eslint/eslint-plugin": "^5.59.2",
"@typescript-eslint/eslint-plugin": "^6.5.0",
"@typescript-eslint/parser": "^6.5.0",
"eslint": "^8.39.0",
"eslint-plugin-prettier": "^5.0.0",
+16
View File
@@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.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)
### Features
* should be able to access shared item revisions as third party user ([#807](https://github.com/standardnotes/server/issues/807)) ([794cd87](https://github.com/standardnotes/server/commit/794cd8734acf89fb29f09dfb169a3f08f252bb6a))
## [1.26.3](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.26.2...@standardnotes/domain-core@1.26.3) (2023-09-04)
**Note:** Version bump only for package @standardnotes/domain-core
## [1.26.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.26.1...@standardnotes/domain-core@1.26.2) (2023-09-01)
**Note:** Version bump only for package @standardnotes/domain-core
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-core",
"version": "1.26.2",
"version": "1.28.0",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -29,8 +29,8 @@
"devDependencies": {
"@types/jest": "^29.5.1",
"@types/node": "^20.5.7",
"@types/uuid": "^9.0.2",
"@typescript-eslint/eslint-plugin": "^5.59.2",
"@types/uuid": "^9.0.3",
"@typescript-eslint/eslint-plugin": "^6.5.0",
"@typescript-eslint/parser": "^6.5.0",
"eslint": "^8.39.0",
"eslint-plugin-prettier": "^5.0.0",
@@ -9,6 +9,7 @@ export class RoleName extends ValueObject<RoleNameProps> {
ProUser: 'PRO_USER',
InternalTeamUser: 'INTERNAL_TEAM_USER',
TransitionUser: 'TRANSITION_USER',
VaultsUser: 'VAULTS_USER',
}
get value(): string {
@@ -32,6 +33,7 @@ export class RoleName extends ValueObject<RoleNameProps> {
)
case RoleName.NAMES.CoreUser:
case RoleName.NAMES.TransitionUser:
case RoleName.NAMES.VaultsUser:
return [RoleName.NAMES.CoreUser, RoleName.NAMES.TransitionUser].includes(roleName.value)
/*istanbul ignore next*/
default:
@@ -51,7 +51,7 @@ describe('RoleNameCollection', () => {
})
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 roleNames = valueOrError.getValue()
@@ -63,6 +63,18 @@ describe('RoleNameCollection', () => {
roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.CoreUser).getValue()),
).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]
valueOrError = RoleNameCollection.create(roles)
roleNames = valueOrError.getValue()
@@ -0,0 +1,23 @@
import { Timestamps } from './Timestamps'
describe('Timestamps', () => {
it('should create a value object', () => {
const valueOrError = Timestamps.create(123, 234)
expect(valueOrError.isFailed()).toBeFalsy()
expect(valueOrError.getValue().createdAt).toEqual(123)
expect(valueOrError.getValue().updatedAt).toEqual(234)
})
it('should not create an invalid value object', () => {
const valueOrError = Timestamps.create('' as unknown as number, 123)
expect(valueOrError.isFailed()).toBeTruthy()
})
it('should not create an invalid value object', () => {
const valueOrError = Timestamps.create(123, '' as unknown as number)
expect(valueOrError.isFailed()).toBeTruthy()
})
})
@@ -16,12 +16,12 @@ export class Timestamps extends ValueObject<TimestampsProps> {
}
static create(createdAt: number, updatedAt: number): Result<Timestamps> {
if (isNaN(createdAt)) {
if (isNaN(createdAt) || typeof createdAt !== 'number') {
return Result.fail<Timestamps>(
`Could not create Timestamps. Creation date should be a number, given: ${createdAt}`,
)
}
if (isNaN(updatedAt)) {
if (isNaN(updatedAt) || typeof updatedAt !== 'number') {
return Result.fail<Timestamps>(`Could not create Timestamps. Update date should be a number, given: ${updatedAt}`)
}
@@ -1,6 +1,7 @@
import { SharedVaultUserPermission, Timestamps, Uuid } from '@standardnotes/domain-core'
import { SharedVaultUserPermission } from './SharedVaultUserPermission'
import { SharedVaultUser } from './SharedVaultUser'
import { Uuid } from '../Common/Uuid'
import { Timestamps } from '../Common/Timestamps'
describe('SharedVaultUser', () => {
it('should create an entity', () => {
@@ -1,5 +1,6 @@
import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
import { Entity } from '../Core/Entity'
import { Result } from '../Core/Result'
import { UniqueEntityId } from '../Core/UniqueEntityId'
import { SharedVaultUserProps } from './SharedVaultUserProps'
export class SharedVaultUser extends Entity<SharedVaultUserProps> {
@@ -0,0 +1,10 @@
import { Timestamps } from '../Common/Timestamps'
import { Uuid } from '../Common/Uuid'
import { SharedVaultUserPermission } from './SharedVaultUserPermission'
export interface SharedVaultUserProps {
sharedVaultUuid: Uuid
userUuid: Uuid
permission: SharedVaultUserPermission
timestamps: Timestamps
}
+2
View File
@@ -59,8 +59,10 @@ export * from './Service/ServiceIdentifier'
export * from './Service/ServiceIdentifierProps'
export * from './Service/ServiceInterface'
export * from './SharedVault/SharedVaultUser'
export * from './SharedVault/SharedVaultUserPermission'
export * from './SharedVault/SharedVaultUserPermissionProps'
export * from './SharedVault/SharedVaultUserProps'
export * from './Subscription/SubscriptionPlanName'
export * from './Subscription/SubscriptionPlanNameProps'
+12
View File
@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [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)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.12.21](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.12.20...@standardnotes/domain-events-infra@1.12.21) (2023-09-04)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.12.20](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.12.19...@standardnotes/domain-events-infra@1.12.20) (2023-09-01)
**Note:** Version bump only for package @standardnotes/domain-events-infra
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-events-infra",
"version": "1.12.20",
"version": "1.12.23",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -35,7 +35,7 @@
"devDependencies": {
"@types/ioredis": "^5.0.0",
"@types/jest": "^29.5.1",
"@typescript-eslint/eslint-plugin": "^5.59.2",
"@typescript-eslint/eslint-plugin": "^6.5.0",
"@typescript-eslint/parser": "^6.5.0",
"eslint": "^8.39.0",
"eslint-plugin-prettier": "^5.0.0",
+16
View File
@@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [2.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)
### Features
* should be able to access shared item revisions as third party user ([#807](https://github.com/standardnotes/server/issues/807)) ([794cd87](https://github.com/standardnotes/server/commit/794cd8734acf89fb29f09dfb169a3f08f252bb6a))
## [2.122.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.122.1...@standardnotes/domain-events@2.122.2) (2023-09-04)
**Note:** Version bump only for package @standardnotes/domain-events
## [2.122.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.122.0...@standardnotes/domain-events@2.122.1) (2023-09-01)
**Note:** Version bump only for package @standardnotes/domain-events
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-events",
"version": "2.122.1",
"version": "2.124.0",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -28,7 +28,7 @@
},
"devDependencies": {
"@types/jest": "^29.5.1",
"@typescript-eslint/eslint-plugin": "^5.59.2",
"@typescript-eslint/eslint-plugin": "^6.5.0",
"@typescript-eslint/parser": "^6.5.0",
"eslint": "^8.39.0",
"eslint-plugin-prettier": "^5.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,7 @@
import { DomainEventInterface } from './DomainEventInterface'
import { UserAddedToSharedVaultEventPayload } from './UserAddedToSharedVaultEventPayload'
export interface UserAddedToSharedVaultEvent extends DomainEventInterface {
type: 'USER_ADDED_TO_SHARED_VAULT'
payload: UserAddedToSharedVaultEventPayload
}
@@ -0,0 +1,7 @@
export interface UserAddedToSharedVaultEventPayload {
sharedVaultUuid: string
userUuid: string
permission: string
createdAt: number
updatedAt: number
}
@@ -0,0 +1,7 @@
import { DomainEventInterface } from './DomainEventInterface'
import { UserRemovedFromSharedVaultEventPayload } from './UserRemovedFromSharedVaultEventPayload'
export interface UserRemovedFromSharedVaultEvent extends DomainEventInterface {
type: 'USER_REMOVED_FROM_SHARED_VAULT'
payload: UserRemovedFromSharedVaultEventPayload
}
@@ -0,0 +1,4 @@
export interface UserRemovedFromSharedVaultEventPayload {
sharedVaultUuid: string
userUuid: string
}
@@ -32,6 +32,8 @@ export * from './Event/FileUploadedEvent'
export * from './Event/FileUploadedEventPayload'
export * from './Event/ItemDumpedEvent'
export * from './Event/ItemDumpedEventPayload'
export * from './Event/ItemRemovedFromSharedVaultEvent'
export * from './Event/ItemRemovedFromSharedVaultEventPayload'
export * from './Event/ItemRevisionCreationRequestedEvent'
export * from './Event/ItemRevisionCreationRequestedEventPayload'
export * from './Event/ListedAccountCreatedEvent'
@@ -96,6 +98,8 @@ export * from './Event/SubscriptionSyncRequestedEvent'
export * from './Event/SubscriptionSyncRequestedEventPayload'
export * from './Event/TransitionStatusUpdatedEvent'
export * from './Event/TransitionStatusUpdatedEventPayload'
export * from './Event/UserAddedToSharedVaultEvent'
export * from './Event/UserAddedToSharedVaultEventPayload'
export * from './Event/UserDisabledSessionUserAgentLoggingEvent'
export * from './Event/UserDisabledSessionUserAgentLoggingEventPayload'
export * from './Event/UserEmailChangedEvent'
@@ -104,6 +108,8 @@ export * from './Event/UserInvitedToSharedVaultEvent'
export * from './Event/UserInvitedToSharedVaultEventPayload'
export * from './Event/UserRegisteredEvent'
export * from './Event/UserRegisteredEventPayload'
export * from './Event/UserRemovedFromSharedVaultEvent'
export * from './Event/UserRemovedFromSharedVaultEventPayload'
export * from './Event/UserRolesChangedEvent'
export * from './Event/UserRolesChangedEventPayload'
export * from './Event/WebSocketMessageRequestedEvent'
+16
View File
@@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.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)
**Note:** Version bump only for package @standardnotes/event-store
## [1.11.31](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.30...@standardnotes/event-store@1.11.31) (2023-09-04)
**Note:** Version bump only for package @standardnotes/event-store
## [1.11.30](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.29...@standardnotes/event-store@1.11.30) (2023-09-01)
**Note:** Version bump only for package @standardnotes/event-store
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/event-store",
"version": "1.11.30",
"version": "1.11.34",
"description": "Event Store Service",
"private": true,
"main": "dist/src/index.js",
@@ -22,7 +22,7 @@
"@types/ioredis": "^5.0.0",
"@types/jest": "^29.5.1",
"@types/nodemailer": "^6.4.1",
"@typescript-eslint/eslint-plugin": "^5.59.2",
"@typescript-eslint/eslint-plugin": "^6.5.0",
"@typescript-eslint/parser": "^6.5.0",
"eslint": "^8.39.0",
"eslint-plugin-prettier": "^5.0.0",

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