mirror of
https://github.com/standardnotes/server
synced 2026-01-22 02:04:30 -05:00
Compare commits
44 Commits
@standardn
...
@standardn
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c067cb9fe4 | ||
|
|
6b2389cdc3 | ||
|
|
d93916b159 | ||
|
|
c34f548e45 | ||
|
|
6fcd56cc86 | ||
|
|
8f88a87c93 | ||
|
|
f8c2f84322 | ||
|
|
46c4947871 | ||
|
|
64759ec2da | ||
|
|
5f7e768e64 | ||
|
|
4bc189f1c5 | ||
|
|
71721ab198 | ||
|
|
5536a48966 | ||
|
|
f77e29d3c9 | ||
|
|
4b1fc718a2 | ||
|
|
1708c3f8a0 | ||
|
|
352e02028d | ||
|
|
1bbb639c83 | ||
|
|
c14265f103 | ||
|
|
c030a6b3d8 | ||
|
|
af997ea658 | ||
|
|
efa4d7fc60 | ||
|
|
f714aaa0e9 | ||
|
|
aee6e60583 | ||
|
|
4e602687d5 | ||
|
|
d026152ac8 | ||
|
|
3f21a358d2 | ||
|
|
dc55e47c98 | ||
|
|
3b804e2321 | ||
|
|
b32f851a90 | ||
|
|
479d20e76f | ||
|
|
fae4553fc8 | ||
|
|
cb74b23e45 | ||
|
|
af8f12c33a | ||
|
|
a148c4d1f6 | ||
|
|
f7190c0c9c | ||
|
|
c00d7765a9 | ||
|
|
2b651d86e2 | ||
|
|
9be3517093 | ||
|
|
fcfedaf7e7 | ||
|
|
0b82794e9c | ||
|
|
2a52e398cb | ||
|
|
c31e882ad2 | ||
|
|
2f0903e0eb |
4
.github/workflows/common-e2e.yml
vendored
4
.github/workflows/common-e2e.yml
vendored
@@ -115,6 +115,8 @@ jobs:
|
||||
echo "DB_TYPE=${{ matrix.db_type }}" >> packages/home-server/.env
|
||||
echo "REDIS_URL=redis://cache" >> packages/home-server/.env
|
||||
echo "CACHE_TYPE=${{ matrix.cache_type }}" >> packages/home-server/.env
|
||||
echo "FILES_SERVER_URL=http://localhost:3123" >> packages/home-server/.env
|
||||
echo "E2E_TESTING=true" >> packages/home-server/.env
|
||||
|
||||
- name: Run Server
|
||||
run: nohup yarn workspace @standardnotes/home-server start &
|
||||
@@ -125,4 +127,4 @@ 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 1200000 -f http://localhost:9001/mocha/test.html?skip_paid_features=true
|
||||
run: yarn dlx mocha-headless-chrome --timeout 1200000 -f http://localhost:9001/mocha/test.html
|
||||
|
||||
@@ -3,6 +3,28 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.25.4](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.25.3...@standardnotes/analytics@2.25.4) (2023-07-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
## [2.25.3](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.25.2...@standardnotes/analytics@2.25.3) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
## [2.25.2](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.25.1...@standardnotes/analytics@2.25.2) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
## [2.25.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.25.0...@standardnotes/analytics@2.25.1) (2023-07-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
# [2.25.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.24.9...@standardnotes/analytics@2.25.0) (2023-07-17)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** refactor syncing to decouple getting and saving items ([#659](https://github.com/standardnotes/server/issues/659)) ([cb74b23](https://github.com/standardnotes/server/commit/cb74b23e45b207136e299ce8a3db2c04dc87e21e))
|
||||
|
||||
## [2.24.9](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.24.8...@standardnotes/analytics@2.24.9) (2023-07-12)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/analytics",
|
||||
"version": "2.24.9",
|
||||
"version": "2.25.4",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -3,10 +3,6 @@ import { Result, Entity, UniqueEntityId } from '@standardnotes/domain-core'
|
||||
import { StatisticMeasureProps } from './StatisticMeasureProps'
|
||||
|
||||
export class StatisticMeasure extends Entity<StatisticMeasureProps> {
|
||||
get id(): UniqueEntityId {
|
||||
return this._id
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return this.props.name.value
|
||||
}
|
||||
|
||||
@@ -3,10 +3,6 @@ import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
|
||||
import { SubscriptionProps } from './SubscriptionProps'
|
||||
|
||||
export class Subscription extends Entity<SubscriptionProps> {
|
||||
get id(): UniqueEntityId {
|
||||
return this._id
|
||||
}
|
||||
|
||||
private constructor(props: SubscriptionProps, id?: UniqueEntityId) {
|
||||
super(props, id)
|
||||
}
|
||||
|
||||
@@ -3,10 +3,6 @@ import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
|
||||
import { UserProps } from './UserProps'
|
||||
|
||||
export class User extends Entity<UserProps> {
|
||||
get id(): UniqueEntityId {
|
||||
return this._id
|
||||
}
|
||||
|
||||
private constructor(props: UserProps, id?: UniqueEntityId) {
|
||||
super(props, id)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,40 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.67.3](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.67.2...@standardnotes/api-gateway@1.67.3) (2023-07-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
## [1.67.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.67.1...@standardnotes/api-gateway@1.67.2) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
## [1.67.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.67.0...@standardnotes/api-gateway@1.67.1) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
# [1.67.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.66.1...@standardnotes/api-gateway@1.67.0) (2023-07-20)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** add shared vaults, invites, messages and notifications to sync response ([#665](https://github.com/standardnotes/api-gateway/issues/665)) ([efa4d7f](https://github.com/standardnotes/api-gateway/commit/efa4d7fc6007ef668e3de3b04853ac11b2d13c30))
|
||||
|
||||
## [1.66.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.66.0...@standardnotes/api-gateway@1.66.1) (2023-07-19)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add missing imports and exports for controllers ([#664](https://github.com/standardnotes/api-gateway/issues/664)) ([aee6e60](https://github.com/standardnotes/api-gateway/commit/aee6e6058359e2b5231cc13387656f837699300f))
|
||||
|
||||
# [1.66.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.65.7...@standardnotes/api-gateway@1.66.0) (2023-07-19)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** add persistence of shared vaults with users and invites + controllers ([#662](https://github.com/standardnotes/api-gateway/issues/662)) ([3f21a35](https://github.com/standardnotes/api-gateway/commit/3f21a358d24d70daf541aa62dc86cd9e29500e62))
|
||||
|
||||
## [1.65.7](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.65.6...@standardnotes/api-gateway@1.65.7) (2023-07-17)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
## [1.65.6](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.65.5...@standardnotes/api-gateway@1.65.6) (2023-07-12)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
@@ -16,8 +16,10 @@ import '../src/Controller/v1/OfflineController'
|
||||
import '../src/Controller/v1/FilesController'
|
||||
import '../src/Controller/v1/SubscriptionInvitesController'
|
||||
import '../src/Controller/v1/AuthenticatorsController'
|
||||
import '../src/Controller/v1/AsymmetricMessagesController'
|
||||
import '../src/Controller/v1/MessagesController'
|
||||
import '../src/Controller/v1/SharedVaultsController'
|
||||
import '../src/Controller/v1/SharedVaultInvitesController'
|
||||
import '../src/Controller/v1/SharedVaultUsersController'
|
||||
|
||||
import '../src/Controller/v2/PaymentsControllerV2'
|
||||
import '../src/Controller/v2/ActionsControllerV2'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/api-gateway",
|
||||
"version": "1.65.6",
|
||||
"version": "1.67.3",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@ export * from './SubscriptionTokenAuthMiddleware'
|
||||
export * from './TokenAuthenticationMethod'
|
||||
export * from './WebSocketAuthMiddleware'
|
||||
export * from './v1/ActionsController'
|
||||
export * from './v1/AsymmetricMessagesController'
|
||||
export * from './v1/MessagesController'
|
||||
export * from './v1/AuthenticatorsController'
|
||||
export * from './v1/FilesController'
|
||||
export * from './v1/InvoicesController'
|
||||
@@ -13,6 +13,8 @@ export * from './v1/OfflineController'
|
||||
export * from './v1/PaymentsController'
|
||||
export * from './v1/RevisionsController'
|
||||
export * from './v1/SessionsController'
|
||||
export * from './v1/SharedVaultInvitesController'
|
||||
export * from './v1/SharedVaultUsersController'
|
||||
export * from './v1/SharedVaultsController'
|
||||
export * from './v1/SubscriptionInvitesController'
|
||||
export * from './v1/TokensController'
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
import { Request, Response } from 'express'
|
||||
import { inject } from 'inversify'
|
||||
import { BaseHttpController, controller, all } from 'inversify-express-utils'
|
||||
import { TYPES } from '../../Bootstrap/Types'
|
||||
import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
|
||||
|
||||
@controller('/v1/asymmetric-messages')
|
||||
export class AsymmetricMessagesController extends BaseHttpController {
|
||||
constructor(@inject(TYPES.ServiceProxy) private serviceProxy: ServiceProxyInterface) {
|
||||
super()
|
||||
}
|
||||
|
||||
@all('*', TYPES.RequiredCrossServiceTokenMiddleware)
|
||||
async subscriptions(request: Request, response: Response): Promise<void> {
|
||||
await this.serviceProxy.callSyncingServer(request, response, request.path.replace('/v1/', ''), request.body)
|
||||
}
|
||||
}
|
||||
70
packages/api-gateway/src/Controller/v1/MessagesController.ts
Normal file
70
packages/api-gateway/src/Controller/v1/MessagesController.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { Request, Response } from 'express'
|
||||
import { inject } from 'inversify'
|
||||
import { BaseHttpController, controller, httpDelete, httpGet, httpPost } from 'inversify-express-utils'
|
||||
import { TYPES } from '../../Bootstrap/Types'
|
||||
import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
|
||||
import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface'
|
||||
|
||||
@controller('/v1/messages', TYPES.RequiredCrossServiceTokenMiddleware)
|
||||
export class MessagesController extends BaseHttpController {
|
||||
constructor(
|
||||
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface,
|
||||
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
@httpGet('/')
|
||||
async getMessages(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier('GET', 'messages/'),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
|
||||
@httpGet('/outbound')
|
||||
async getMessagesSent(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier('GET', 'messages/outbound'),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
|
||||
@httpPost('/')
|
||||
async sendMessage(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier('POST', 'messages/'),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
|
||||
@httpDelete('/inbound')
|
||||
async deleteMessagesSentToUser(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier('DELETE', 'messages/inbound'),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
|
||||
@httpDelete('/:messageUuid')
|
||||
async deleteMessage(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier(
|
||||
'DELETE',
|
||||
'messages/:messageUuid',
|
||||
request.params.messageUuid,
|
||||
),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
import { Request, Response } from 'express'
|
||||
import { inject } from 'inversify'
|
||||
import { BaseHttpController, controller, httpDelete, httpGet, httpPatch, httpPost } from 'inversify-express-utils'
|
||||
import { TYPES } from '../../Bootstrap/Types'
|
||||
import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
|
||||
import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface'
|
||||
|
||||
@controller('/v1/shared-vaults', TYPES.RequiredCrossServiceTokenMiddleware)
|
||||
export class SharedVaultInvitesController extends BaseHttpController {
|
||||
constructor(
|
||||
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface,
|
||||
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
@httpPost('/:sharedVaultUuid/invites')
|
||||
async createSharedVaultInvite(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier(
|
||||
'POST',
|
||||
'shared-vaults/:sharedVaultUuid/invites',
|
||||
request.params.sharedVaultUuid,
|
||||
),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
|
||||
@httpPatch('/:sharedVaultUuid/invites/:inviteUuid')
|
||||
async updateSharedVaultInvite(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier(
|
||||
'PATCH',
|
||||
'shared-vaults/:sharedVaultUuid/invites/:inviteUuid',
|
||||
request.params.sharedVaultUuid,
|
||||
request.params.inviteUuid,
|
||||
),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
|
||||
@httpPost('/:sharedVaultUuid/invites/:inviteUuid/accept')
|
||||
async acceptSharedVaultInvite(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier(
|
||||
'POST',
|
||||
'shared-vaults/:sharedVaultUuid/invites/:inviteUuid/accept',
|
||||
request.params.sharedVaultUuid,
|
||||
request.params.inviteUuid,
|
||||
),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
|
||||
@httpPost('/:sharedVaultUuid/invites/:inviteUuid/decline')
|
||||
async declineSharedVaultInvite(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier(
|
||||
'POST',
|
||||
'shared-vaults/:sharedVaultUuid/invites/:inviteUuid/decline',
|
||||
request.params.sharedVaultUuid,
|
||||
request.params.inviteUuid,
|
||||
),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
|
||||
@httpDelete('/invites/inbound')
|
||||
async deleteInboundUserInvites(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier('DELETE', 'shared-vaults/invites/inbound'),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
|
||||
@httpGet('/invites/outbound')
|
||||
async getOutboundUserInvites(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier('GET', 'shared-vaults/invites/outbound'),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
|
||||
@httpGet('/invites')
|
||||
async getUserInvites(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier('GET', 'shared-vaults/invites'),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
|
||||
@httpGet('/:sharedVaultUuid/invites')
|
||||
async getSharedVaultInvites(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier(
|
||||
'GET',
|
||||
'shared-vaults/:sharedVaultUuid/invites',
|
||||
request.params.sharedVaultUuid,
|
||||
),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
|
||||
@httpDelete('/:sharedVaultUuid/invites/:inviteUuid')
|
||||
async deleteSharedVaultInvite(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier(
|
||||
'DELETE',
|
||||
'shared-vaults/:sharedVaultUuid/invites/:inviteUuid',
|
||||
request.params.sharedVaultUuid,
|
||||
request.params.inviteUuid,
|
||||
),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
|
||||
@httpDelete('/:sharedVaultUuid/invites')
|
||||
async deleteAllSharedVaultInvites(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier(
|
||||
'DELETE',
|
||||
'shared-vaults/:sharedVaultUuid/invites',
|
||||
request.params.sharedVaultUuid,
|
||||
),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import { Request, Response } from 'express'
|
||||
import { inject } from 'inversify'
|
||||
import { BaseHttpController, controller, httpDelete, httpGet } from 'inversify-express-utils'
|
||||
import { TYPES } from '../../Bootstrap/Types'
|
||||
import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
|
||||
import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface'
|
||||
|
||||
@controller('/v1/shared-vaults/:sharedVaultUuid/users', TYPES.RequiredCrossServiceTokenMiddleware)
|
||||
export class SharedVaultUsersController extends BaseHttpController {
|
||||
constructor(
|
||||
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface,
|
||||
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
@httpGet('/')
|
||||
async getSharedVaultUsers(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier(
|
||||
'GET',
|
||||
'shared-vaults/:sharedVaultUuid/users',
|
||||
request.params.sharedVaultUuid,
|
||||
),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
|
||||
@httpDelete('/:userUuid')
|
||||
async removeUserFromSharedVault(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier(
|
||||
'DELETE',
|
||||
'shared-vaults/:sharedVaultUuid/users/:userUuid',
|
||||
request.params.sharedVaultUuid,
|
||||
request.params.userUuid,
|
||||
),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,64 @@
|
||||
import { Request, Response } from 'express'
|
||||
import { inject } from 'inversify'
|
||||
import { BaseHttpController, controller, all } from 'inversify-express-utils'
|
||||
import { BaseHttpController, controller, httpDelete, httpGet, httpPost } from 'inversify-express-utils'
|
||||
import { TYPES } from '../../Bootstrap/Types'
|
||||
import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
|
||||
import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface'
|
||||
|
||||
@controller('/v1/shared-vaults')
|
||||
@controller('/v1/shared-vaults', TYPES.RequiredCrossServiceTokenMiddleware)
|
||||
export class SharedVaultsController extends BaseHttpController {
|
||||
constructor(@inject(TYPES.ServiceProxy) private serviceProxy: ServiceProxyInterface) {
|
||||
constructor(
|
||||
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface,
|
||||
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
@all('*', TYPES.RequiredCrossServiceTokenMiddleware)
|
||||
async subscriptions(request: Request, response: Response): Promise<void> {
|
||||
await this.serviceProxy.callSyncingServer(request, response, request.path.replace('/v1/', ''), request.body)
|
||||
@httpGet('/')
|
||||
async getSharedVaults(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier('GET', 'shared-vaults/'),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
|
||||
@httpPost('/')
|
||||
async createSharedVault(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier('POST', 'shared-vaults/'),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
|
||||
@httpDelete('/:sharedVaultUuid')
|
||||
async deleteSharedVault(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier(
|
||||
'DELETE',
|
||||
'shared-vaults/:sharedVaultUuid',
|
||||
request.params.sharedVaultUuid,
|
||||
),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
|
||||
@httpPost('/:sharedVaultUuid/valet-tokens')
|
||||
async createValetTokenForSharedVaultFile(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callSyncingServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier(
|
||||
'POST',
|
||||
'shared-vaults/:sharedVaultUuid/valet-tokens',
|
||||
request.params.sharedVaultUuid,
|
||||
),
|
||||
request.body,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,31 @@ export class EndpointResolver implements EndpointResolverInterface {
|
||||
['[GET]:items/:itemUuid/revisions', 'revisions.revisions.getRevisions'],
|
||||
['[GET]:items/:itemUuid/revisions/:id', 'revisions.revisions.getRevision'],
|
||||
['[DELETE]:items/:itemUuid/revisions/:id', 'revisions.revisions.deleteRevision'],
|
||||
// Messages Controller
|
||||
['[GET]:messages/', 'sync.messages.get-received'],
|
||||
['[GET]:messages/outbound', 'sync.messages.get-sent'],
|
||||
['[POST]:messages/', 'sync.messages.send'],
|
||||
['[DELETE]:messages/inbound', 'sync.messages.delete-all'],
|
||||
['[DELETE]:messages/:messageUuid', 'sync.messages.delete'],
|
||||
// Shared Vaults Controller
|
||||
['[GET]:shared-vaults/', 'sync.shared-vaults.get-vaults'],
|
||||
['[POST]:shared-vaults/', 'sync.shared-vaults.create-vault'],
|
||||
['[DELETE]:shared-vaults/:sharedVaultUuid', 'sync.shared-vaults.delete-vault'],
|
||||
['[POST]:shared-vaults/:sharedVaultUuid/valet-tokens', 'sync.shared-vaults.create-file-valet-token'],
|
||||
// Shared Vault Invites Controller
|
||||
['[POST]:shared-vaults/:sharedVaultUuid/invites', 'sync.shared-vault-invites.create'],
|
||||
['[PATCH]:shared-vaults/:sharedVaultUuid/invites/:inviteUuid', 'sync.shared-vault-invites.update'],
|
||||
['[POST]:shared-vaults/:sharedVaultUuid/invites/:inviteUuid/accept', 'sync.shared-vault-invites.accept'],
|
||||
['[POST]:shared-vaults/:sharedVaultUuid/invites/:inviteUuid/decline', 'sync.shared-vault-invites.decline'],
|
||||
['[DELETE]:shared-vaults/invites/inbound', 'sync.shared-vault-invites.delete-inbound'],
|
||||
['[GET]:shared-vaults/invites/outbound', 'sync.shared-vault-invites.get-outbound'],
|
||||
['[GET]:shared-vaults/invites', 'sync.shared-vault-invites.get-user-invites'],
|
||||
['[GET]:shared-vaults/:sharedVaultUuid/invites', 'sync.shared-vault-invites.get-vault-invites'],
|
||||
['[DELETE]:shared-vaults/:sharedVaultUuid/invites/:inviteUuid', 'sync.shared-vault-invites.delete-invite'],
|
||||
['[DELETE]:shared-vaults/:sharedVaultUuid/invites', 'sync.shared-vault-invites.delete-all'],
|
||||
// Shared Vault Users Controller
|
||||
['[GET]:shared-vaults/:sharedVaultUuid/users', 'sync.shared-vault-users.get-users'],
|
||||
['[DELETE]:shared-vaults/:sharedVaultUuid/users/:userUuid', 'sync.shared-vault-users.remove-user'],
|
||||
])
|
||||
|
||||
resolveEndpointOrMethodIdentifier(method: string, endpoint: string, ...params: string[]): string {
|
||||
@@ -75,7 +100,7 @@ export class EndpointResolver implements EndpointResolverInterface {
|
||||
const identifier = this.endpointToIdentifierMap.get(`[${method}]:${endpoint}`)
|
||||
|
||||
if (!identifier) {
|
||||
throw new Error(`Endpoint ${endpoint} not found`)
|
||||
throw new Error(`Endpoint [${method}]:${endpoint} not found`)
|
||||
}
|
||||
|
||||
return identifier
|
||||
|
||||
@@ -3,6 +3,52 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.126.3](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.126.2...@standardnotes/auth-server@1.126.3) (2023-07-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
## [1.126.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.126.1...@standardnotes/auth-server@1.126.2) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
## [1.126.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.126.0...@standardnotes/auth-server@1.126.1) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
# [1.126.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.125.1...@standardnotes/auth-server@1.126.0) (2023-07-20)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** add shared vaults, invites, messages and notifications to sync response ([#665](https://github.com/standardnotes/server/issues/665)) ([efa4d7f](https://github.com/standardnotes/server/commit/efa4d7fc6007ef668e3de3b04853ac11b2d13c30))
|
||||
|
||||
## [1.125.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.125.0...@standardnotes/auth-server@1.125.1) (2023-07-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
# [1.125.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.124.2...@standardnotes/auth-server@1.125.0) (2023-07-17)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** refactor syncing to decouple getting and saving items ([#659](https://github.com/standardnotes/server/issues/659)) ([cb74b23](https://github.com/standardnotes/server/commit/cb74b23e45b207136e299ce8a3db2c04dc87e21e))
|
||||
|
||||
## [1.124.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.124.1...@standardnotes/auth-server@1.124.2) (2023-07-14)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **home-server:** allow custom atributtes for activating premium features ([f7190c0](https://github.com/standardnotes/server/commit/f7190c0c9c2d105f97d1cf980ce6a4f0dae34805))
|
||||
|
||||
## [1.124.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.124.0...@standardnotes/auth-server@1.124.1) (2023-07-13)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **files:** handling unlimited storage quota on home server ([9be3517](https://github.com/standardnotes/server/commit/9be3517093f8dd7bbdd7507c1e2ff059e6c9a889))
|
||||
|
||||
# [1.124.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.123.2...@standardnotes/auth-server@1.124.0) (2023-07-13)
|
||||
|
||||
### Features
|
||||
|
||||
* **auth:** add overriding subscription settings on home server ([#656](https://github.com/standardnotes/server/issues/656)) ([0b82794](https://github.com/standardnotes/server/commit/0b82794e9c7ed82cfc08a92eafc016fbde5c4fcc))
|
||||
|
||||
## [1.123.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.123.1...@standardnotes/auth-server@1.123.2) (2023-07-12)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddNotifications1688540448427 implements MigrationInterface {
|
||||
name = 'AddNotifications1688540448427'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE `notifications` (`uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `type` varchar(36) NOT NULL, `payload` text NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `index_notifications_on_user_uuid` (`user_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX `index_notifications_on_user_uuid` ON `notifications`')
|
||||
await queryRunner.query('DROP TABLE `notifications`')
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class RemoveNotifications1688540448428 implements MigrationInterface {
|
||||
name = 'RemoveNotifications1688540448428'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX `index_notifications_on_user_uuid` ON `notifications`')
|
||||
await queryRunner.query('DROP TABLE `notifications`')
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE `notifications` (`uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `type` varchar(36) NOT NULL, `payload` text NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `index_notifications_on_user_uuid` (`user_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddNotifications1688540623272 implements MigrationInterface {
|
||||
name = 'AddNotifications1688540623272'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE "notifications" ("uuid" varchar PRIMARY KEY NOT NULL, "user_uuid" varchar(36) NOT NULL, "type" varchar(36) NOT NULL, "payload" text NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
|
||||
)
|
||||
await queryRunner.query('CREATE INDEX "index_notifications_on_user_uuid" ON "notifications" ("user_uuid") ')
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX "index_notifications_on_user_uuid"')
|
||||
await queryRunner.query('DROP TABLE "notifications"')
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class RemoveNotifications1688540623273 implements MigrationInterface {
|
||||
name = 'RemoveNotifications1688540623273'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX "index_notifications_on_user_uuid"')
|
||||
await queryRunner.query('DROP TABLE "notifications"')
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE "notifications" ("uuid" varchar PRIMARY KEY NOT NULL, "user_uuid" varchar(36) NOT NULL, "type" varchar(36) NOT NULL, "payload" text NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
|
||||
)
|
||||
await queryRunner.query('CREATE INDEX "index_notifications_on_user_uuid" ON "notifications" ("user_uuid") ')
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/auth-server",
|
||||
"version": "1.123.2",
|
||||
"version": "1.126.3",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { Result, ServiceInterface } from '@standardnotes/domain-core'
|
||||
|
||||
export interface AuthServiceInterface extends ServiceInterface {
|
||||
activatePremiumFeatures(username: string): Promise<Result<string>>
|
||||
activatePremiumFeatures(dto: {
|
||||
username: string
|
||||
subscriptionPlanName?: string
|
||||
endsAt?: Date
|
||||
}): Promise<Result<string>>
|
||||
}
|
||||
|
||||
@@ -793,6 +793,7 @@ export class ContainerConfigLoader {
|
||||
new ActivatePremiumFeatures(
|
||||
container.get(TYPES.Auth_UserRepository),
|
||||
container.get(TYPES.Auth_UserSubscriptionRepository),
|
||||
container.get(TYPES.Auth_SubscriptionSettingService),
|
||||
container.get(TYPES.Auth_RoleService),
|
||||
container.get(TYPES.Auth_Timer),
|
||||
),
|
||||
|
||||
@@ -24,14 +24,18 @@ export class Service implements AuthServiceInterface {
|
||||
this.serviceContainer.register(this.getId(), this)
|
||||
}
|
||||
|
||||
async activatePremiumFeatures(username: string): Promise<Result<string>> {
|
||||
async activatePremiumFeatures(dto: {
|
||||
username: string
|
||||
subscriptionPlanName?: string
|
||||
endsAt?: Date
|
||||
}): Promise<Result<string>> {
|
||||
if (!this.container) {
|
||||
return Result.fail('Container not initialized')
|
||||
}
|
||||
|
||||
const activatePremiumFeatures = this.container.get(TYPES.Auth_ActivatePremiumFeatures) as ActivatePremiumFeatures
|
||||
|
||||
return activatePremiumFeatures.execute({ username })
|
||||
return activatePremiumFeatures.execute(dto)
|
||||
}
|
||||
|
||||
async handleRequest(request: never, response: never, endpointOrMethodIdentifier: string): Promise<unknown> {
|
||||
|
||||
@@ -3,10 +3,6 @@ import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
|
||||
import { AuthenticatorProps } from './AuthenticatorProps'
|
||||
|
||||
export class Authenticator extends Entity<AuthenticatorProps> {
|
||||
get id(): UniqueEntityId {
|
||||
return this._id
|
||||
}
|
||||
|
||||
private constructor(props: AuthenticatorProps, id?: UniqueEntityId) {
|
||||
super(props, id)
|
||||
}
|
||||
|
||||
@@ -3,10 +3,6 @@ import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
|
||||
import { AuthenticatorChallengeProps } from './AuthenticatorChallengeProps'
|
||||
|
||||
export class AuthenticatorChallenge extends Entity<AuthenticatorChallengeProps> {
|
||||
get id(): UniqueEntityId {
|
||||
return this._id
|
||||
}
|
||||
|
||||
private constructor(props: AuthenticatorChallengeProps, id?: UniqueEntityId) {
|
||||
super(props, id)
|
||||
}
|
||||
|
||||
@@ -3,10 +3,6 @@ import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
|
||||
import { EmergencyAccessInvitationProps } from './EmergencyAccessInvitationProps'
|
||||
|
||||
export class EmergencyAccessInvitation extends Entity<EmergencyAccessInvitationProps> {
|
||||
get id(): UniqueEntityId {
|
||||
return this._id
|
||||
}
|
||||
|
||||
private constructor(props: EmergencyAccessInvitationProps, id?: UniqueEntityId) {
|
||||
super(props, id)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@ import { UserSubscriptionServiceInterface } from '../Subscription/UserSubscripti
|
||||
describe('FileRemovedEventHandler', () => {
|
||||
let userSubscriptionService: UserSubscriptionServiceInterface
|
||||
let logger: Logger
|
||||
let user: User
|
||||
let regularUser: User
|
||||
let sharedUser: User
|
||||
let event: FileRemovedEvent
|
||||
let subscriptionSettingService: SubscriptionSettingServiceInterface
|
||||
let regularSubscription: UserSubscription
|
||||
@@ -22,20 +23,24 @@ describe('FileRemovedEventHandler', () => {
|
||||
const createHandler = () => new FileRemovedEventHandler(userSubscriptionService, subscriptionSettingService, logger)
|
||||
|
||||
beforeEach(() => {
|
||||
user = {
|
||||
regularUser = {
|
||||
uuid: '123',
|
||||
} as jest.Mocked<User>
|
||||
|
||||
sharedUser = {
|
||||
uuid: '234',
|
||||
} as jest.Mocked<User>
|
||||
|
||||
regularSubscription = {
|
||||
uuid: '1-2-3',
|
||||
subscriptionType: UserSubscriptionType.Regular,
|
||||
user: Promise.resolve(user),
|
||||
user: Promise.resolve(regularUser),
|
||||
} as jest.Mocked<UserSubscription>
|
||||
|
||||
sharedSubscription = {
|
||||
uuid: '2-3-4',
|
||||
subscriptionType: UserSubscriptionType.Shared,
|
||||
user: Promise.resolve(user),
|
||||
user: Promise.resolve(sharedUser),
|
||||
} as jest.Mocked<UserSubscription>
|
||||
|
||||
userSubscriptionService = {} as jest.Mocked<UserSubscriptionServiceInterface>
|
||||
@@ -93,10 +98,11 @@ describe('FileRemovedEventHandler', () => {
|
||||
unencryptedValue: '222',
|
||||
serverEncryptionVersion: 0,
|
||||
},
|
||||
user: regularUser,
|
||||
userSubscription: {
|
||||
uuid: '1-2-3',
|
||||
subscriptionType: 'regular',
|
||||
user: Promise.resolve(user),
|
||||
user: Promise.resolve(regularUser),
|
||||
},
|
||||
})
|
||||
})
|
||||
@@ -118,10 +124,11 @@ describe('FileRemovedEventHandler', () => {
|
||||
unencryptedValue: '222',
|
||||
serverEncryptionVersion: 0,
|
||||
},
|
||||
user: regularUser,
|
||||
userSubscription: {
|
||||
uuid: '1-2-3',
|
||||
subscriptionType: 'regular',
|
||||
user: Promise.resolve(user),
|
||||
user: Promise.resolve(regularUser),
|
||||
},
|
||||
})
|
||||
|
||||
@@ -132,10 +139,11 @@ describe('FileRemovedEventHandler', () => {
|
||||
unencryptedValue: '222',
|
||||
serverEncryptionVersion: 0,
|
||||
},
|
||||
user: sharedUser,
|
||||
userSubscription: {
|
||||
uuid: '2-3-4',
|
||||
subscriptionType: 'shared',
|
||||
user: Promise.resolve(user),
|
||||
user: Promise.resolve(sharedUser),
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
@@ -51,6 +51,7 @@ export class FileRemovedEventHandler implements DomainEventHandlerInterface {
|
||||
|
||||
await this.subscriptionSettingService.createOrReplace({
|
||||
userSubscription: subscription,
|
||||
user,
|
||||
props: {
|
||||
name: SettingName.NAMES.FileUploadBytesUsed,
|
||||
unencryptedValue: (+bytesUsed - byteSize).toString(),
|
||||
|
||||
@@ -76,6 +76,7 @@ describe('FileUploadedEventHandler', () => {
|
||||
unencryptedValue: '123',
|
||||
serverEncryptionVersion: 0,
|
||||
},
|
||||
user,
|
||||
userSubscription: {
|
||||
uuid: '1-2-3',
|
||||
subscriptionType: 'regular',
|
||||
@@ -118,6 +119,7 @@ describe('FileUploadedEventHandler', () => {
|
||||
unencryptedValue: '468',
|
||||
serverEncryptionVersion: 0,
|
||||
},
|
||||
user,
|
||||
userSubscription: {
|
||||
uuid: '1-2-3',
|
||||
subscriptionType: 'regular',
|
||||
@@ -143,6 +145,7 @@ describe('FileUploadedEventHandler', () => {
|
||||
unencryptedValue: '468',
|
||||
serverEncryptionVersion: 0,
|
||||
},
|
||||
user,
|
||||
userSubscription: {
|
||||
uuid: '1-2-3',
|
||||
subscriptionType: 'regular',
|
||||
@@ -157,6 +160,7 @@ describe('FileUploadedEventHandler', () => {
|
||||
unencryptedValue: '468',
|
||||
serverEncryptionVersion: 0,
|
||||
},
|
||||
user,
|
||||
userSubscription: {
|
||||
uuid: '2-3-4',
|
||||
subscriptionType: 'shared',
|
||||
|
||||
@@ -9,6 +9,7 @@ import { SubscriptionSettingServiceInterface } from '../Setting/SubscriptionSett
|
||||
import { UserSubscription } from '../Subscription/UserSubscription'
|
||||
import { UserSubscriptionServiceInterface } from '../Subscription/UserSubscriptionServiceInterface'
|
||||
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
|
||||
import { User } from '../User/User'
|
||||
|
||||
@injectable()
|
||||
export class FileUploadedEventHandler implements DomainEventHandlerInterface {
|
||||
@@ -36,14 +37,18 @@ export class FileUploadedEventHandler implements DomainEventHandlerInterface {
|
||||
return
|
||||
}
|
||||
|
||||
await this.updateUploadBytesUsedSetting(regularSubscription, event.payload.fileByteSize)
|
||||
await this.updateUploadBytesUsedSetting(regularSubscription, user, event.payload.fileByteSize)
|
||||
|
||||
if (sharedSubscription !== null) {
|
||||
await this.updateUploadBytesUsedSetting(sharedSubscription, event.payload.fileByteSize)
|
||||
await this.updateUploadBytesUsedSetting(sharedSubscription, user, event.payload.fileByteSize)
|
||||
}
|
||||
}
|
||||
|
||||
private async updateUploadBytesUsedSetting(subscription: UserSubscription, byteSize: number): Promise<void> {
|
||||
private async updateUploadBytesUsedSetting(
|
||||
subscription: UserSubscription,
|
||||
user: User,
|
||||
byteSize: number,
|
||||
): Promise<void> {
|
||||
let bytesUsed = '0'
|
||||
const bytesUsedSetting = await this.subscriptionSettingService.findSubscriptionSettingWithDecryptedValue({
|
||||
userUuid: (await subscription.user).uuid,
|
||||
@@ -56,6 +61,7 @@ export class FileUploadedEventHandler implements DomainEventHandlerInterface {
|
||||
|
||||
await this.subscriptionSettingService.createOrReplace({
|
||||
userSubscription: subscription,
|
||||
user,
|
||||
props: {
|
||||
name: SettingName.NAMES.FileUploadBytesUsed,
|
||||
unencryptedValue: (+bytesUsed + byteSize).toString(),
|
||||
|
||||
@@ -114,8 +114,6 @@ describe('SubscriptionPurchasedEventHandler', () => {
|
||||
|
||||
expect(subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription).toHaveBeenCalledWith(
|
||||
subscription,
|
||||
SubscriptionName.ProPlan,
|
||||
'123',
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -66,11 +66,7 @@ export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInte
|
||||
|
||||
await this.addUserRole(user, event.payload.subscriptionName)
|
||||
|
||||
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(
|
||||
userSubscription,
|
||||
event.payload.subscriptionName,
|
||||
user.uuid,
|
||||
)
|
||||
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(userSubscription)
|
||||
}
|
||||
|
||||
private async addUserRole(user: User, subscriptionName: string): Promise<void> {
|
||||
|
||||
@@ -94,8 +94,6 @@ describe('SubscriptionReassignedEventHandler', () => {
|
||||
|
||||
expect(subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription).toHaveBeenCalledWith(
|
||||
subscription,
|
||||
SubscriptionName.ProPlan,
|
||||
'123',
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -63,11 +63,7 @@ export class SubscriptionReassignedEventHandler implements DomainEventHandlerInt
|
||||
},
|
||||
})
|
||||
|
||||
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(
|
||||
userSubscription,
|
||||
event.payload.subscriptionName,
|
||||
user.uuid,
|
||||
)
|
||||
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(userSubscription)
|
||||
}
|
||||
|
||||
private async addUserRole(user: User, subscriptionName: string): Promise<void> {
|
||||
|
||||
@@ -129,8 +129,6 @@ describe('SubscriptionSyncRequestedEventHandler', () => {
|
||||
|
||||
expect(subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription).toHaveBeenCalledWith(
|
||||
subscription,
|
||||
SubscriptionName.ProPlan,
|
||||
'123',
|
||||
)
|
||||
|
||||
expect(settingService.createOrReplace).toHaveBeenCalledWith({
|
||||
|
||||
@@ -95,11 +95,7 @@ export class SubscriptionSyncRequestedEventHandler implements DomainEventHandler
|
||||
|
||||
await this.roleService.addUserRole(user, event.payload.subscriptionName)
|
||||
|
||||
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(
|
||||
userSubscription,
|
||||
event.payload.subscriptionName,
|
||||
user.uuid,
|
||||
)
|
||||
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(userSubscription)
|
||||
|
||||
await this.settingService.createOrReplace({
|
||||
user,
|
||||
|
||||
@@ -3,10 +3,6 @@ import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
|
||||
import { SessionTraceProps } from './SessionTraceProps'
|
||||
|
||||
export class SessionTrace extends Entity<SessionTraceProps> {
|
||||
get id(): UniqueEntityId {
|
||||
return this._id
|
||||
}
|
||||
|
||||
private constructor(props: SessionTraceProps, id?: UniqueEntityId) {
|
||||
super(props, id)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { UserSubscription } from '../Subscription/UserSubscription'
|
||||
import { User } from '../User/User'
|
||||
import { SubscriptionSettingProps } from './SubscriptionSettingProps'
|
||||
|
||||
export type CreateOrReplaceSubscriptionSettingDTO = {
|
||||
userSubscription: UserSubscription
|
||||
user: User
|
||||
props: SubscriptionSettingProps
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ describe('SubscriptionSettingService', () => {
|
||||
userSubscription = {
|
||||
uuid: '1-2-3',
|
||||
user: Promise.resolve(user),
|
||||
planName: SubscriptionName.PlusPlan,
|
||||
} as jest.Mocked<UserSubscription>
|
||||
|
||||
setting = {
|
||||
@@ -97,15 +98,70 @@ describe('SubscriptionSettingService', () => {
|
||||
})
|
||||
|
||||
it('should create default settings for a subscription', async () => {
|
||||
await createService().applyDefaultSubscriptionSettingsForSubscription(
|
||||
userSubscription,
|
||||
SubscriptionName.PlusPlan,
|
||||
'1-2-3',
|
||||
)
|
||||
await createService().applyDefaultSubscriptionSettingsForSubscription(userSubscription)
|
||||
|
||||
expect(subscriptionSettingRepository.save).toHaveBeenCalledWith(setting)
|
||||
})
|
||||
|
||||
it('should create default settings for a subscription with overrides', async () => {
|
||||
subscriptionSettingsAssociationService.getDefaultSettingsAndValuesForSubscriptionName = jest.fn().mockReturnValue(
|
||||
new Map([
|
||||
[
|
||||
SettingName.NAMES.FileUploadBytesUsed,
|
||||
{
|
||||
value: '0',
|
||||
sensitive: 0,
|
||||
serverEncryptionVersion: EncryptionVersion.Unencrypted,
|
||||
replaceable: false,
|
||||
},
|
||||
],
|
||||
[
|
||||
SettingName.NAMES.FileUploadBytesLimit,
|
||||
{
|
||||
value: '345',
|
||||
sensitive: 0,
|
||||
serverEncryptionVersion: EncryptionVersion.Unencrypted,
|
||||
replaceable: true,
|
||||
},
|
||||
],
|
||||
]),
|
||||
)
|
||||
|
||||
await createService().applyDefaultSubscriptionSettingsForSubscription(
|
||||
userSubscription,
|
||||
new Map([[SettingName.NAMES.FileUploadBytesLimit, '123']]),
|
||||
)
|
||||
|
||||
expect(factory.createSubscriptionSetting).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
{
|
||||
name: SettingName.NAMES.FileUploadBytesUsed,
|
||||
sensitive: 0,
|
||||
serverEncryptionVersion: EncryptionVersion.Unencrypted,
|
||||
unencryptedValue: '0',
|
||||
},
|
||||
{
|
||||
planName: SubscriptionName.PlusPlan,
|
||||
user: Promise.resolve(user),
|
||||
uuid: '1-2-3',
|
||||
},
|
||||
)
|
||||
expect(factory.createSubscriptionSetting).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
{
|
||||
name: SettingName.NAMES.FileUploadBytesLimit,
|
||||
sensitive: 0,
|
||||
serverEncryptionVersion: EncryptionVersion.Unencrypted,
|
||||
unencryptedValue: '123',
|
||||
},
|
||||
{
|
||||
planName: SubscriptionName.PlusPlan,
|
||||
user: Promise.resolve(user),
|
||||
uuid: '1-2-3',
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
it('should throw error if subscription setting is invalid', async () => {
|
||||
subscriptionSettingsAssociationService.getDefaultSettingsAndValuesForSubscriptionName = jest.fn().mockReturnValue(
|
||||
new Map([
|
||||
@@ -121,13 +177,7 @@ describe('SubscriptionSettingService', () => {
|
||||
]),
|
||||
)
|
||||
|
||||
await expect(
|
||||
createService().applyDefaultSubscriptionSettingsForSubscription(
|
||||
userSubscription,
|
||||
SubscriptionName.PlusPlan,
|
||||
'1-2-3',
|
||||
),
|
||||
).rejects.toThrow()
|
||||
await expect(createService().applyDefaultSubscriptionSettingsForSubscription(userSubscription)).rejects.toThrow()
|
||||
})
|
||||
|
||||
it('should throw error if setting name is not a subscription setting when applying defaults', async () => {
|
||||
@@ -145,13 +195,7 @@ describe('SubscriptionSettingService', () => {
|
||||
]),
|
||||
)
|
||||
|
||||
await expect(
|
||||
createService().applyDefaultSubscriptionSettingsForSubscription(
|
||||
userSubscription,
|
||||
SubscriptionName.PlusPlan,
|
||||
'1-2-3',
|
||||
),
|
||||
).rejects.toThrow()
|
||||
await expect(createService().applyDefaultSubscriptionSettingsForSubscription(userSubscription)).rejects.toThrow()
|
||||
})
|
||||
|
||||
it('should reassign existing default settings for a subscription if it is not replaceable', async () => {
|
||||
@@ -170,11 +214,7 @@ describe('SubscriptionSettingService', () => {
|
||||
)
|
||||
subscriptionSettingRepository.findLastByNameAndUserSubscriptionUuid = jest.fn().mockReturnValue(setting)
|
||||
|
||||
await createService().applyDefaultSubscriptionSettingsForSubscription(
|
||||
userSubscription,
|
||||
SubscriptionName.PlusPlan,
|
||||
'1-2-3',
|
||||
)
|
||||
await createService().applyDefaultSubscriptionSettingsForSubscription(userSubscription)
|
||||
|
||||
expect(subscriptionSettingRepository.save).toHaveBeenCalled()
|
||||
})
|
||||
@@ -195,11 +235,7 @@ describe('SubscriptionSettingService', () => {
|
||||
)
|
||||
subscriptionSettingRepository.findLastByNameAndUserSubscriptionUuid = jest.fn().mockReturnValue(null)
|
||||
|
||||
await createService().applyDefaultSubscriptionSettingsForSubscription(
|
||||
userSubscription,
|
||||
SubscriptionName.PlusPlan,
|
||||
'1-2-3',
|
||||
)
|
||||
await createService().applyDefaultSubscriptionSettingsForSubscription(userSubscription)
|
||||
|
||||
expect(subscriptionSettingRepository.save).toHaveBeenCalledWith(setting)
|
||||
})
|
||||
@@ -225,11 +261,7 @@ describe('SubscriptionSettingService', () => {
|
||||
} as jest.Mocked<UserSubscription>,
|
||||
])
|
||||
|
||||
await createService().applyDefaultSubscriptionSettingsForSubscription(
|
||||
userSubscription,
|
||||
SubscriptionName.PlusPlan,
|
||||
'1-2-3',
|
||||
)
|
||||
await createService().applyDefaultSubscriptionSettingsForSubscription(userSubscription)
|
||||
|
||||
expect(subscriptionSettingRepository.save).toHaveBeenCalledWith(setting)
|
||||
})
|
||||
@@ -239,11 +271,7 @@ describe('SubscriptionSettingService', () => {
|
||||
.fn()
|
||||
.mockReturnValue(undefined)
|
||||
|
||||
await createService().applyDefaultSubscriptionSettingsForSubscription(
|
||||
userSubscription,
|
||||
SubscriptionName.PlusPlan,
|
||||
'1-2-3',
|
||||
)
|
||||
await createService().applyDefaultSubscriptionSettingsForSubscription(userSubscription)
|
||||
|
||||
expect(subscriptionSettingRepository.save).not.toHaveBeenCalled()
|
||||
})
|
||||
@@ -251,6 +279,7 @@ describe('SubscriptionSettingService', () => {
|
||||
it("should create setting if it doesn't exist", async () => {
|
||||
const result = await createService().createOrReplace({
|
||||
userSubscription,
|
||||
user,
|
||||
props: {
|
||||
name: SettingName.NAMES.FileUploadBytesLimit,
|
||||
unencryptedValue: 'value',
|
||||
@@ -266,6 +295,7 @@ describe('SubscriptionSettingService', () => {
|
||||
await expect(
|
||||
createService().createOrReplace({
|
||||
userSubscription,
|
||||
user,
|
||||
props: {
|
||||
name: 'invalid',
|
||||
unencryptedValue: 'value',
|
||||
@@ -280,6 +310,7 @@ describe('SubscriptionSettingService', () => {
|
||||
await expect(
|
||||
createService().createOrReplace({
|
||||
userSubscription,
|
||||
user,
|
||||
props: {
|
||||
name: SettingName.NAMES.DropboxBackupFrequency,
|
||||
unencryptedValue: 'value',
|
||||
@@ -295,6 +326,7 @@ describe('SubscriptionSettingService', () => {
|
||||
|
||||
const result = await createService().createOrReplace({
|
||||
userSubscription,
|
||||
user,
|
||||
props: {
|
||||
uuid: '1-2-3',
|
||||
name: SettingName.NAMES.FileUploadBytesLimit,
|
||||
@@ -312,6 +344,7 @@ describe('SubscriptionSettingService', () => {
|
||||
|
||||
const result = await createService().createOrReplace({
|
||||
userSubscription,
|
||||
user,
|
||||
props: {
|
||||
...setting,
|
||||
unencryptedValue: 'value',
|
||||
@@ -327,6 +360,7 @@ describe('SubscriptionSettingService', () => {
|
||||
|
||||
const result = await createService().createOrReplace({
|
||||
userSubscription,
|
||||
user,
|
||||
props: {
|
||||
...setting,
|
||||
uuid: '1-2-3',
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { SubscriptionName } from '@standardnotes/common'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
@@ -36,17 +35,20 @@ export class SubscriptionSettingService implements SubscriptionSettingServiceInt
|
||||
|
||||
async applyDefaultSubscriptionSettingsForSubscription(
|
||||
userSubscription: UserSubscription,
|
||||
subscriptionName: SubscriptionName,
|
||||
userUuid: string,
|
||||
overrides?: Map<string, string>,
|
||||
): Promise<void> {
|
||||
const defaultSettingsWithValues =
|
||||
await this.subscriptionSettingAssociationService.getDefaultSettingsAndValuesForSubscriptionName(subscriptionName)
|
||||
await this.subscriptionSettingAssociationService.getDefaultSettingsAndValuesForSubscriptionName(
|
||||
userSubscription.planName,
|
||||
)
|
||||
if (defaultSettingsWithValues === undefined) {
|
||||
this.logger.warn(`Could not find settings for subscription: ${subscriptionName}`)
|
||||
this.logger.warn(`Could not find settings for subscription: ${userSubscription.planName}`)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const user = await userSubscription.user
|
||||
|
||||
for (const settingNameString of defaultSettingsWithValues.keys()) {
|
||||
const settingNameOrError = SettingName.create(settingNameString)
|
||||
if (settingNameOrError.isFailed()) {
|
||||
@@ -59,7 +61,11 @@ export class SubscriptionSettingService implements SubscriptionSettingServiceInt
|
||||
|
||||
const setting = defaultSettingsWithValues.get(settingName.value) as SettingDescription
|
||||
if (!setting.replaceable) {
|
||||
const existingSetting = await this.findPreviousSubscriptionSetting(settingName, userSubscription.uuid, userUuid)
|
||||
const existingSetting = await this.findPreviousSubscriptionSetting(
|
||||
settingName,
|
||||
userSubscription.uuid,
|
||||
user.uuid,
|
||||
)
|
||||
if (existingSetting !== null) {
|
||||
existingSetting.userSubscription = Promise.resolve(userSubscription)
|
||||
await this.subscriptionSettingRepository.save(existingSetting)
|
||||
@@ -68,11 +74,17 @@ export class SubscriptionSettingService implements SubscriptionSettingServiceInt
|
||||
}
|
||||
}
|
||||
|
||||
let unencryptedValue = setting.value
|
||||
if (overrides && overrides.has(settingName.value)) {
|
||||
unencryptedValue = overrides.get(settingName.value) as string
|
||||
}
|
||||
|
||||
await this.createOrReplace({
|
||||
userSubscription,
|
||||
user,
|
||||
props: {
|
||||
name: settingName.value,
|
||||
unencryptedValue: setting.value,
|
||||
unencryptedValue,
|
||||
serverEncryptionVersion: setting.serverEncryptionVersion,
|
||||
sensitive: setting.sensitive,
|
||||
},
|
||||
@@ -109,7 +121,7 @@ export class SubscriptionSettingService implements SubscriptionSettingServiceInt
|
||||
async createOrReplace(
|
||||
dto: CreateOrReplaceSubscriptionSettingDTO,
|
||||
): Promise<CreateOrReplaceSubscriptionSettingResponse> {
|
||||
const { userSubscription, props } = dto
|
||||
const { userSubscription, user, props } = dto
|
||||
|
||||
const settingNameOrError = SettingName.create(props.name)
|
||||
if (settingNameOrError.isFailed()) {
|
||||
@@ -121,7 +133,6 @@ export class SubscriptionSettingService implements SubscriptionSettingServiceInt
|
||||
throw new Error(`Setting ${settingName.value} is not a subscription setting`)
|
||||
}
|
||||
|
||||
const user = await userSubscription.user
|
||||
const existing = await this.findSubscriptionSettingWithDecryptedValue({
|
||||
userUuid: user.uuid,
|
||||
userSubscriptionUuid: userSubscription.uuid,
|
||||
|
||||
@@ -8,8 +8,7 @@ import { SubscriptionSetting } from './SubscriptionSetting'
|
||||
export interface SubscriptionSettingServiceInterface {
|
||||
applyDefaultSubscriptionSettingsForSubscription(
|
||||
userSubscription: UserSubscription,
|
||||
subscriptionName: string,
|
||||
userUuid: string,
|
||||
overrides?: Map<string, string>,
|
||||
): Promise<void>
|
||||
createOrReplace(dto: CreateOrReplaceSubscriptionSettingDTO): Promise<CreateOrReplaceSubscriptionSettingResponse>
|
||||
findSubscriptionSettingWithDecryptedValue(dto: FindSubscriptionSettingDTO): Promise<SubscriptionSetting | null>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { SettingDescription } from './SettingDescription'
|
||||
|
||||
export interface SubscriptionSettingsAssociationServiceInterface {
|
||||
getDefaultSettingsAndValuesForSubscriptionName(
|
||||
subscriptionName: SubscriptionName,
|
||||
subscriptionName: string,
|
||||
): Promise<Map<string, SettingDescription> | undefined>
|
||||
getFileUploadLimit(subscriptionName: SubscriptionName): Promise<number>
|
||||
}
|
||||
|
||||
@@ -106,8 +106,6 @@ describe('AcceptSharedSubscriptionInvitation', () => {
|
||||
expect(roleService.addUserRole).toHaveBeenCalledWith(invitee, 'PLUS_PLAN')
|
||||
expect(subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription).toHaveBeenCalledWith(
|
||||
inviteeSubscription,
|
||||
'PLUS_PLAN',
|
||||
'123',
|
||||
)
|
||||
})
|
||||
|
||||
@@ -148,8 +146,6 @@ describe('AcceptSharedSubscriptionInvitation', () => {
|
||||
expect(roleService.addUserRole).toHaveBeenCalledWith(invitee, 'PLUS_PLAN')
|
||||
expect(subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription).toHaveBeenCalledWith(
|
||||
inviteeSubscription,
|
||||
'PLUS_PLAN',
|
||||
'123',
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -92,11 +92,7 @@ export class AcceptSharedSubscriptionInvitation implements UseCaseInterface {
|
||||
|
||||
await this.addUserRole(invitee, inviterUserSubscription.planName as SubscriptionName)
|
||||
|
||||
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(
|
||||
inviteeSubscription,
|
||||
inviteeSubscription.planName as SubscriptionName,
|
||||
invitee.uuid,
|
||||
)
|
||||
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(inviteeSubscription)
|
||||
|
||||
return {
|
||||
success: true,
|
||||
|
||||
@@ -5,16 +5,24 @@ import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
|
||||
|
||||
import { ActivatePremiumFeatures } from './ActivatePremiumFeatures'
|
||||
import { User } from '../../User/User'
|
||||
import { SubscriptionSettingServiceInterface } from '../../Setting/SubscriptionSettingServiceInterface'
|
||||
|
||||
describe('ActivatePremiumFeatures', () => {
|
||||
let userRepository: UserRepositoryInterface
|
||||
let userSubscriptionRepository: UserSubscriptionRepositoryInterface
|
||||
let subscriptionSettingsService: SubscriptionSettingServiceInterface
|
||||
let roleService: RoleServiceInterface
|
||||
let timer: TimerInterface
|
||||
let user: User
|
||||
|
||||
const createUseCase = () =>
|
||||
new ActivatePremiumFeatures(userRepository, userSubscriptionRepository, roleService, timer)
|
||||
new ActivatePremiumFeatures(
|
||||
userRepository,
|
||||
userSubscriptionRepository,
|
||||
subscriptionSettingsService,
|
||||
roleService,
|
||||
timer,
|
||||
)
|
||||
|
||||
beforeEach(() => {
|
||||
user = {} as jest.Mocked<User>
|
||||
@@ -32,6 +40,9 @@ describe('ActivatePremiumFeatures', () => {
|
||||
timer.getTimestampInMicroseconds = jest.fn().mockReturnValue(123456789)
|
||||
timer.convertDateToMicroseconds = jest.fn().mockReturnValue(123456789)
|
||||
timer.getUTCDateNDaysAhead = jest.fn().mockReturnValue(new Date('2024-01-01T00:00:00.000Z'))
|
||||
|
||||
subscriptionSettingsService = {} as jest.Mocked<SubscriptionSettingServiceInterface>
|
||||
subscriptionSettingsService.applyDefaultSubscriptionSettingsForSubscription = jest.fn()
|
||||
})
|
||||
|
||||
it('should return error when username is invalid', async () => {
|
||||
@@ -64,4 +75,28 @@ describe('ActivatePremiumFeatures', () => {
|
||||
expect(userSubscriptionRepository.save).toHaveBeenCalled()
|
||||
expect(roleService.addUserRole).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should save a subscription with custom plan name and endsAt', async () => {
|
||||
const useCase = createUseCase()
|
||||
|
||||
const result = await useCase.execute({
|
||||
username: 'test@test.te',
|
||||
subscriptionPlanName: 'PRO_PLAN',
|
||||
endsAt: new Date('2024-01-01T00:00:00.000Z'),
|
||||
})
|
||||
|
||||
expect(result.isFailed()).toBe(false)
|
||||
})
|
||||
|
||||
it('should fail when subscription plan name is invalid', async () => {
|
||||
const useCase = createUseCase()
|
||||
|
||||
const result = await useCase.execute({
|
||||
username: 'test@test.te',
|
||||
subscriptionPlanName: 'some invalid plan name',
|
||||
endsAt: new Date('2024-01-01T00:00:00.000Z'),
|
||||
})
|
||||
|
||||
expect(result.isFailed()).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -7,11 +7,14 @@ import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
|
||||
import { UserSubscription } from '../../Subscription/UserSubscription'
|
||||
import { UserSubscriptionType } from '../../Subscription/UserSubscriptionType'
|
||||
import { ActivatePremiumFeaturesDTO } from './ActivatePremiumFeaturesDTO'
|
||||
import { SubscriptionSettingServiceInterface } from '../../Setting/SubscriptionSettingServiceInterface'
|
||||
import { SettingName } from '@standardnotes/settings'
|
||||
|
||||
export class ActivatePremiumFeatures implements UseCaseInterface<string> {
|
||||
constructor(
|
||||
private userRepository: UserRepositoryInterface,
|
||||
private userSubscriptionRepository: UserSubscriptionRepositoryInterface,
|
||||
private subscriptionSettingService: SubscriptionSettingServiceInterface,
|
||||
private roleService: RoleServiceInterface,
|
||||
private timer: TimerInterface,
|
||||
) {}
|
||||
@@ -27,22 +30,35 @@ export class ActivatePremiumFeatures implements UseCaseInterface<string> {
|
||||
if (user === null) {
|
||||
return Result.fail(`User not found with username: ${username.value}`)
|
||||
}
|
||||
const subscriptionPlanNameString = dto.subscriptionPlanName ?? SubscriptionPlanName.NAMES.ProPlan
|
||||
const subscriptionPlanNameOrError = SubscriptionPlanName.create(subscriptionPlanNameString)
|
||||
if (subscriptionPlanNameOrError.isFailed()) {
|
||||
return Result.fail(subscriptionPlanNameOrError.getError())
|
||||
}
|
||||
const subscriptionPlanName = subscriptionPlanNameOrError.getValue()
|
||||
|
||||
const timestamp = this.timer.getTimestampInMicroseconds()
|
||||
|
||||
const endsAt = dto.endsAt ?? this.timer.getUTCDateNDaysAhead(365)
|
||||
|
||||
const subscription = new UserSubscription()
|
||||
subscription.planName = SubscriptionPlanName.NAMES.ProPlan
|
||||
subscription.planName = subscriptionPlanName.value
|
||||
subscription.user = Promise.resolve(user)
|
||||
subscription.createdAt = timestamp
|
||||
subscription.updatedAt = timestamp
|
||||
subscription.endsAt = this.timer.convertDateToMicroseconds(this.timer.getUTCDateNDaysAhead(365))
|
||||
subscription.endsAt = this.timer.convertDateToMicroseconds(endsAt)
|
||||
subscription.cancelled = false
|
||||
subscription.subscriptionId = 1
|
||||
subscription.subscriptionType = UserSubscriptionType.Regular
|
||||
|
||||
await this.userSubscriptionRepository.save(subscription)
|
||||
|
||||
await this.roleService.addUserRole(user, SubscriptionPlanName.NAMES.ProPlan)
|
||||
await this.roleService.addUserRole(user, subscriptionPlanName.value)
|
||||
|
||||
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(
|
||||
subscription,
|
||||
new Map([[SettingName.NAMES.FileUploadBytesLimit, '-1']]),
|
||||
)
|
||||
|
||||
return Result.ok('Premium features activated.')
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
export interface ActivatePremiumFeaturesDTO {
|
||||
username: string
|
||||
subscriptionPlanName?: string
|
||||
endsAt?: Date
|
||||
}
|
||||
|
||||
@@ -268,6 +268,7 @@ describe('UpdateSetting', () => {
|
||||
serverEncryptionVersion: 1,
|
||||
sensitive: false,
|
||||
},
|
||||
user,
|
||||
userSubscription: regularSubscription,
|
||||
})
|
||||
|
||||
@@ -303,6 +304,7 @@ describe('UpdateSetting', () => {
|
||||
serverEncryptionVersion: 1,
|
||||
sensitive: false,
|
||||
},
|
||||
user,
|
||||
userSubscription: sharedSubscription,
|
||||
})
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ export class UpdateSetting implements UseCaseInterface {
|
||||
|
||||
const response = await this.subscriptionSettingService.createOrReplace({
|
||||
userSubscription: subscription,
|
||||
user,
|
||||
props,
|
||||
})
|
||||
|
||||
|
||||
@@ -3,6 +3,36 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.23.4](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.23.3...@standardnotes/domain-core@1.23.4) (2023-07-26)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **syncing-server:** persisting aggregate changes from root ([#674](https://github.com/standardnotes/server/issues/674)) ([c34f548](https://github.com/standardnotes/server/commit/c34f548e45bbd8defb8d490936e90755fd284e78))
|
||||
|
||||
## [1.23.3](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.23.2...@standardnotes/domain-core@1.23.3) (2023-07-21)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **domain-core:** notification payload creation from string ([1708c3f](https://github.com/standardnotes/server/commit/1708c3f8a00897369585e1ef8022950a7c3c610e))
|
||||
|
||||
## [1.23.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.23.1...@standardnotes/domain-core@1.23.2) (2023-07-21)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* user notifications structure ([#667](https://github.com/standardnotes/server/issues/667)) ([1bbb639](https://github.com/standardnotes/server/commit/1bbb639c83922ec09e3778f85419d76669d36ae3))
|
||||
|
||||
## [1.23.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.23.0...@standardnotes/domain-core@1.23.1) (2023-07-19)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **syncing-server:** add missing messages and key system identifier sql representations ([#663](https://github.com/standardnotes/server/issues/663)) ([d026152](https://github.com/standardnotes/server/commit/d026152ac8cb2ecda2eee8d3f7385d655b210938))
|
||||
|
||||
# [1.23.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.22.0...@standardnotes/domain-core@1.23.0) (2023-07-17)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** refactor syncing to decouple getting and saving items ([#659](https://github.com/standardnotes/server/issues/659)) ([cb74b23](https://github.com/standardnotes/server/commit/cb74b23e45b207136e299ce8a3db2c04dc87e21e))
|
||||
|
||||
# [1.22.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.21.1...@standardnotes/domain-core@1.22.0) (2023-07-12)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/domain-core",
|
||||
"version": "1.22.0",
|
||||
"version": "1.23.4",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -4,10 +4,6 @@ import { UniqueEntityId } from '../Core/UniqueEntityId'
|
||||
import { CacheEntryProps } from './CacheEntryProps'
|
||||
|
||||
export class CacheEntry extends Entity<CacheEntryProps> {
|
||||
get id(): UniqueEntityId {
|
||||
return this._id
|
||||
}
|
||||
|
||||
private constructor(props: CacheEntryProps, id?: UniqueEntityId) {
|
||||
super(props, id)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
/* istanbul ignore file */
|
||||
|
||||
import { Change } from './Change'
|
||||
import { Entity } from './Entity'
|
||||
import { UniqueEntityId } from './UniqueEntityId'
|
||||
|
||||
export abstract class Aggregate<T> extends Entity<T> {
|
||||
get id(): UniqueEntityId {
|
||||
return this._id
|
||||
private changesOnAggregateRoot: Change[] = []
|
||||
|
||||
addChange(change: Change): void {
|
||||
this.changesOnAggregateRoot.push(change)
|
||||
}
|
||||
|
||||
flushChanges(): void {
|
||||
this.changesOnAggregateRoot = []
|
||||
}
|
||||
|
||||
getChanges(): Change[] {
|
||||
return this.changesOnAggregateRoot
|
||||
}
|
||||
}
|
||||
|
||||
26
packages/domain-core/src/Domain/Core/Change.ts
Normal file
26
packages/domain-core/src/Domain/Core/Change.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
/* istanbul ignore file */
|
||||
|
||||
import { ChangeProps } from './ChangeProps'
|
||||
import { Result } from './Result'
|
||||
|
||||
export class Change {
|
||||
static readonly TYPES = {
|
||||
Add: 'add',
|
||||
Remove: 'remove',
|
||||
Modify: 'modify',
|
||||
}
|
||||
|
||||
public readonly props: ChangeProps
|
||||
|
||||
constructor(props: ChangeProps) {
|
||||
this.props = Object.freeze(props)
|
||||
}
|
||||
|
||||
static create(props: ChangeProps): Result<Change> {
|
||||
if (!Object.values(Change.TYPES).includes(props.changeType)) {
|
||||
return Result.fail('Invalid change type')
|
||||
}
|
||||
|
||||
return Result.ok(new Change(props))
|
||||
}
|
||||
}
|
||||
9
packages/domain-core/src/Domain/Core/ChangeProps.ts
Normal file
9
packages/domain-core/src/Domain/Core/ChangeProps.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
/* istanbul ignore file */
|
||||
|
||||
import { Entity } from './Entity'
|
||||
|
||||
export interface ChangeProps {
|
||||
aggregateRootUuid: string
|
||||
changeType: string
|
||||
changeData: Entity<unknown>
|
||||
}
|
||||
@@ -9,6 +9,10 @@ export abstract class Entity<T> {
|
||||
this._id = id ? id : new UniqueEntityId()
|
||||
}
|
||||
|
||||
get id(): UniqueEntityId {
|
||||
return this._id
|
||||
}
|
||||
|
||||
public equals(object?: Entity<T>): boolean {
|
||||
if (object == null || object == undefined) {
|
||||
return false
|
||||
|
||||
@@ -78,4 +78,18 @@ describe('Validator', () => {
|
||||
expect(Validator.isNotEmpty(value).isFailed()).toBeTruthy()
|
||||
}
|
||||
})
|
||||
|
||||
describe('is not empty string', () => {
|
||||
it('should not validate invalid string', () => {
|
||||
expect(Validator.isNotEmptyString(123 as unknown as string).isFailed()).toBeTruthy()
|
||||
})
|
||||
|
||||
it('should not validate an empty string', () => {
|
||||
expect(Validator.isNotEmptyString('').isFailed()).toBeTruthy()
|
||||
})
|
||||
|
||||
it('should validate a string', () => {
|
||||
expect(Validator.isNotEmptyString('foo').isFailed()).toBeFalsy()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -42,4 +42,18 @@ export class Validator {
|
||||
|
||||
return Result.ok()
|
||||
}
|
||||
|
||||
static isNotEmptyString(value: unknown): Result<string> {
|
||||
const isStringResult = Validator.isString(value)
|
||||
if (isStringResult.isFailed()) {
|
||||
return isStringResult
|
||||
}
|
||||
|
||||
const isNotEmptyResult = Validator.isNotEmpty(value)
|
||||
if (isNotEmptyResult.isFailed()) {
|
||||
return isNotEmptyResult
|
||||
}
|
||||
|
||||
return Result.ok()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import { ValueObject } from '../Core/ValueObject'
|
||||
import { Result } from '../Core/Result'
|
||||
|
||||
import { NotificationPayloadProps } from './NotificationPayloadProps'
|
||||
import { NotificationType } from './NotificationType'
|
||||
import { Uuid } from '../Common/Uuid'
|
||||
|
||||
export class NotificationPayload extends ValueObject<NotificationPayloadProps> {
|
||||
private constructor(props: NotificationPayloadProps) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
override toString(): string {
|
||||
return JSON.stringify({
|
||||
version: this.props.version,
|
||||
type: this.props.type.value,
|
||||
sharedVaultUuid: this.props.sharedVaultUuid.value,
|
||||
itemUuid: this.props.itemUuid ? this.props.itemUuid.value : undefined,
|
||||
})
|
||||
}
|
||||
|
||||
static createFromString(jsonPayload: string): Result<NotificationPayload> {
|
||||
try {
|
||||
const props = JSON.parse(jsonPayload)
|
||||
|
||||
const typeOrError = NotificationType.create(props.type)
|
||||
if (typeOrError.isFailed()) {
|
||||
return Result.fail<NotificationPayload>(typeOrError.getError())
|
||||
}
|
||||
const type = typeOrError.getValue()
|
||||
|
||||
const sharedVaultUuidOrError = Uuid.create(props.sharedVaultUuid)
|
||||
if (sharedVaultUuidOrError.isFailed()) {
|
||||
return Result.fail<NotificationPayload>(sharedVaultUuidOrError.getError())
|
||||
}
|
||||
const sharedVaultUuid = sharedVaultUuidOrError.getValue()
|
||||
|
||||
let itemUuid: Uuid | undefined = undefined
|
||||
if (props.itemUuid) {
|
||||
const itemUuidOrError = Uuid.create(props.itemUuid)
|
||||
if (itemUuidOrError.isFailed()) {
|
||||
return Result.fail<NotificationPayload>(itemUuidOrError.getError())
|
||||
}
|
||||
itemUuid = itemUuidOrError.getValue()
|
||||
}
|
||||
|
||||
return NotificationPayload.create({
|
||||
version: props.version,
|
||||
type,
|
||||
sharedVaultUuid,
|
||||
itemUuid,
|
||||
})
|
||||
} catch (error) {
|
||||
return Result.fail<NotificationPayload>((error as Error).message)
|
||||
}
|
||||
}
|
||||
|
||||
static create(props: NotificationPayloadProps): Result<NotificationPayload> {
|
||||
if (
|
||||
props.itemUuid === undefined &&
|
||||
props.type.equals(NotificationType.create(NotificationType.TYPES.SharedVaultItemRemoved).getValue())
|
||||
) {
|
||||
return Result.fail<NotificationPayload>(
|
||||
`Item uuid is required for ${NotificationType.TYPES.SharedVaultItemRemoved} notification type`,
|
||||
)
|
||||
}
|
||||
|
||||
return Result.ok<NotificationPayload>(new NotificationPayload(props))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { Uuid } from '../Common/Uuid'
|
||||
import { NotificationType } from './NotificationType'
|
||||
|
||||
export interface NotificationPayloadProps {
|
||||
type: NotificationType
|
||||
sharedVaultUuid: Uuid
|
||||
version: string
|
||||
itemUuid?: Uuid
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ValueObject, Result } from '@standardnotes/domain-core'
|
||||
|
||||
import { Result } from '../Core/Result'
|
||||
import { ValueObject } from '../Core/ValueObject'
|
||||
import { NotificationTypeProps } from './NotificationTypeProps'
|
||||
|
||||
export class NotificationType extends ValueObject<NotificationTypeProps> {
|
||||
@@ -17,9 +17,9 @@ export class NotificationType extends ValueObject<NotificationTypeProps> {
|
||||
}
|
||||
|
||||
static create(notificationType: string): Result<NotificationType> {
|
||||
const isValidPermission = Object.values(this.TYPES).includes(notificationType)
|
||||
if (!isValidPermission) {
|
||||
return Result.fail<NotificationType>(`Invalid shared vault user permission ${notificationType}`)
|
||||
const isValidType = Object.values(this.TYPES).includes(notificationType)
|
||||
if (!isValidType) {
|
||||
return Result.fail<NotificationType>(`Invalid notification type: ${notificationType}`)
|
||||
} else {
|
||||
return Result.ok<NotificationType>(new NotificationType({ value: notificationType }))
|
||||
}
|
||||
@@ -27,6 +27,8 @@ export * from './Common/Uuid'
|
||||
export * from './Common/UuidProps'
|
||||
|
||||
export * from './Core/Aggregate'
|
||||
export * from './Core/Change'
|
||||
export * from './Core/ChangeProps'
|
||||
export * from './Core/Entity'
|
||||
export * from './Core/Id'
|
||||
export * from './Core/Result'
|
||||
@@ -45,6 +47,11 @@ export * from './Env/AbstractEnv'
|
||||
|
||||
export * from './Mapping/MapperInterface'
|
||||
|
||||
export * from './Notification/NotificationPayload'
|
||||
export * from './Notification/NotificationPayloadProps'
|
||||
export * from './Notification/NotificationType'
|
||||
export * from './Notification/NotificationTypeProps'
|
||||
|
||||
export * from './Service/ServiceConfiguration'
|
||||
export * from './Service/ServiceContainer'
|
||||
export * from './Service/ServiceContainerInterface'
|
||||
|
||||
@@ -3,6 +3,26 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.11.11](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.10...@standardnotes/event-store@1.11.11) (2023-07-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
## [1.11.10](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.9...@standardnotes/event-store@1.11.10) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
## [1.11.9](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.8...@standardnotes/event-store@1.11.9) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
## [1.11.8](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.7...@standardnotes/event-store@1.11.8) (2023-07-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
## [1.11.7](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.6...@standardnotes/event-store@1.11.7) (2023-07-17)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
## [1.11.6](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.5...@standardnotes/event-store@1.11.6) (2023-07-12)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/event-store",
|
||||
"version": "1.11.6",
|
||||
"version": "1.11.11",
|
||||
"description": "Event Store Service",
|
||||
"private": true,
|
||||
"main": "dist/src/index.js",
|
||||
|
||||
@@ -3,6 +3,32 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.19.13](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.19.12...@standardnotes/files-server@1.19.13) (2023-07-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
## [1.19.12](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.19.11...@standardnotes/files-server@1.19.12) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
## [1.19.11](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.19.10...@standardnotes/files-server@1.19.11) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
## [1.19.10](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.19.9...@standardnotes/files-server@1.19.10) (2023-07-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
## [1.19.9](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.19.8...@standardnotes/files-server@1.19.9) (2023-07-17)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
## [1.19.8](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.19.7...@standardnotes/files-server@1.19.8) (2023-07-13)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **files:** handling unlimited storage quota on home server ([9be3517](https://github.com/standardnotes/files/commit/9be3517093f8dd7bbdd7507c1e2ff059e6c9a889))
|
||||
|
||||
## [1.19.7](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.19.6...@standardnotes/files-server@1.19.7) (2023-07-12)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/files-server",
|
||||
"version": "1.19.7",
|
||||
"version": "1.19.13",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -135,4 +135,27 @@ describe('FinishUploadSession', () => {
|
||||
expect(fileUploader.finishUploadSession).not.toHaveBeenCalled()
|
||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should ignore the storage quota if user has unlimited storage', async () => {
|
||||
uploadRepository.retrieveUploadChunkResults = jest.fn().mockReturnValue([
|
||||
{ tag: '123', chunkId: 1, chunkSize: 60 },
|
||||
{ tag: '234', chunkId: 2, chunkSize: 10 },
|
||||
{ tag: '345', chunkId: 3, chunkSize: 20 },
|
||||
])
|
||||
|
||||
expect(
|
||||
await createUseCase().execute({
|
||||
resourceRemoteIdentifier: '2-3-4',
|
||||
ownerUuid: '1-2-3',
|
||||
ownerType: 'user',
|
||||
uploadBytesLimit: -1,
|
||||
uploadBytesUsed: 20,
|
||||
}),
|
||||
).toEqual({
|
||||
success: true,
|
||||
})
|
||||
|
||||
expect(fileUploader.finishUploadSession).toHaveBeenCalled()
|
||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -43,8 +43,9 @@ export class FinishUploadSession implements UseCaseInterface {
|
||||
totalFileSize += uploadChunkResult.chunkSize
|
||||
}
|
||||
|
||||
const userHasUnlimitedStorage = dto.uploadBytesLimit === -1
|
||||
const remainingSpaceLeft = dto.uploadBytesLimit - dto.uploadBytesUsed
|
||||
if (remainingSpaceLeft < totalFileSize) {
|
||||
if (!userHasUnlimitedStorage && remainingSpaceLeft < totalFileSize) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Could not finish upload session. You are out of space.',
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
LOG_LEVEL=debug
|
||||
NODE_ENV=development
|
||||
E2E_TESTING=false
|
||||
|
||||
JWT_SECRET=
|
||||
AUTH_JWT_SECRET=
|
||||
|
||||
@@ -3,6 +3,92 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.13.12](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.13.11...@standardnotes/home-server@1.13.12) (2023-07-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.13.11](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.13.10...@standardnotes/home-server@1.13.11) (2023-07-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.13.10](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.13.9...@standardnotes/home-server@1.13.10) (2023-07-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.13.9](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.13.8...@standardnotes/home-server@1.13.9) (2023-07-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.13.8](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.13.7...@standardnotes/home-server@1.13.8) (2023-07-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.13.7](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.13.6...@standardnotes/home-server@1.13.7) (2023-07-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.13.6](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.13.5...@standardnotes/home-server@1.13.6) (2023-07-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.13.5](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.13.4...@standardnotes/home-server@1.13.5) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.13.4](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.13.3...@standardnotes/home-server@1.13.4) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.13.3](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.13.2...@standardnotes/home-server@1.13.3) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.13.2](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.13.1...@standardnotes/home-server@1.13.2) (2023-07-20)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.13.1](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.13.0...@standardnotes/home-server@1.13.1) (2023-07-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
# [1.13.0](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.12.6...@standardnotes/home-server@1.13.0) (2023-07-19)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** add persistence of shared vaults with users and invites + controllers ([#662](https://github.com/standardnotes/server/issues/662)) ([3f21a35](https://github.com/standardnotes/server/commit/3f21a358d24d70daf541aa62dc86cd9e29500e62))
|
||||
|
||||
## [1.12.6](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.12.5...@standardnotes/home-server@1.12.6) (2023-07-18)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.12.5](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.12.4...@standardnotes/home-server@1.12.5) (2023-07-18)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.12.4](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.12.3...@standardnotes/home-server@1.12.4) (2023-07-17)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.12.3](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.12.2...@standardnotes/home-server@1.12.3) (2023-07-14)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **home-server:** allow custom atributtes for activating premium features ([f7190c0](https://github.com/standardnotes/server/commit/f7190c0c9c2d105f97d1cf980ce6a4f0dae34805))
|
||||
|
||||
## [1.12.2](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.12.1...@standardnotes/home-server@1.12.2) (2023-07-13)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.12.1](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.12.0...@standardnotes/home-server@1.12.1) (2023-07-13)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
# [1.12.0](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.41...@standardnotes/home-server@1.12.0) (2023-07-13)
|
||||
|
||||
### Features
|
||||
|
||||
* **home-server:** add activating premium features during an e2e test suite run ([2f0903e](https://github.com/standardnotes/server/commit/2f0903e0ebba95bcf0ece45045dc18e8a988b930))
|
||||
|
||||
## [1.11.41](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.40...@standardnotes/home-server@1.11.41) (2023-07-12)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/home-server",
|
||||
"version": "1.11.41",
|
||||
"version": "1.13.12",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -138,6 +138,22 @@ export class HomeServer implements HomeServerInterface {
|
||||
Disallow: '/',
|
||||
}),
|
||||
)
|
||||
|
||||
if (env.get('E2E_TESTING', true) === 'true') {
|
||||
app.post('/e2e/activate-premium', (request: Request, response: Response) => {
|
||||
void this.activatePremiumFeatures({
|
||||
username: request.body.username,
|
||||
subscriptionPlanName: request.body.subscriptionPlanName,
|
||||
endsAt: request.body.endsAt ? new Date(request.body.endsAt) : undefined,
|
||||
}).then((result) => {
|
||||
if (result.isFailed()) {
|
||||
response.status(400).send({ error: { message: result.getError() } })
|
||||
} else {
|
||||
response.status(200).send({ message: result.getValue() })
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const logger: winston.Logger = winston.loggers.get('home-server')
|
||||
@@ -163,6 +179,8 @@ export class HomeServer implements HomeServerInterface {
|
||||
|
||||
return Result.ok('Server started.')
|
||||
} catch (error) {
|
||||
console.error((error as Error).stack)
|
||||
|
||||
return Result.fail((error as Error).message)
|
||||
}
|
||||
}
|
||||
@@ -200,12 +218,16 @@ export class HomeServer implements HomeServerInterface {
|
||||
return this.serverInstance.address() !== null
|
||||
}
|
||||
|
||||
async activatePremiumFeatures(username: string): Promise<Result<string>> {
|
||||
async activatePremiumFeatures(dto: {
|
||||
username: string
|
||||
subscriptionPlanName?: string
|
||||
endsAt?: Date
|
||||
}): Promise<Result<string>> {
|
||||
if (!this.isRunning() || !this.authService) {
|
||||
return Result.fail('Home server is not running.')
|
||||
}
|
||||
|
||||
return this.authService.activatePremiumFeatures(username)
|
||||
return this.authService.activatePremiumFeatures(dto)
|
||||
}
|
||||
|
||||
private configureLoggers(env: Env, configuration: HomeServerConfiguration): void {
|
||||
|
||||
@@ -3,7 +3,11 @@ import { HomeServerConfiguration } from './HomeServerConfiguration'
|
||||
|
||||
export interface HomeServerInterface {
|
||||
start(configuration?: HomeServerConfiguration): Promise<Result<string>>
|
||||
activatePremiumFeatures(username: string): Promise<Result<string>>
|
||||
activatePremiumFeatures(dto: {
|
||||
username: string
|
||||
subscriptionPlanName?: string
|
||||
endsAt?: Date
|
||||
}): Promise<Result<string>>
|
||||
stop(): Promise<Result<string>>
|
||||
isRunning(): Promise<boolean>
|
||||
}
|
||||
|
||||
@@ -3,6 +3,28 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.25.4](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.25.3...@standardnotes/revisions-server@1.25.4) (2023-07-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
## [1.25.3](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.25.2...@standardnotes/revisions-server@1.25.3) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
## [1.25.2](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.25.1...@standardnotes/revisions-server@1.25.2) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
## [1.25.1](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.25.0...@standardnotes/revisions-server@1.25.1) (2023-07-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
# [1.25.0](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.24.1...@standardnotes/revisions-server@1.25.0) (2023-07-17)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** refactor syncing to decouple getting and saving items ([#659](https://github.com/standardnotes/server/issues/659)) ([cb74b23](https://github.com/standardnotes/server/commit/cb74b23e45b207136e299ce8a3db2c04dc87e21e))
|
||||
|
||||
## [1.24.1](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.24.0...@standardnotes/revisions-server@1.24.1) (2023-07-12)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/revisions-server",
|
||||
"version": "1.24.1",
|
||||
"version": "1.25.4",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -3,10 +3,6 @@ import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
|
||||
import { RevisionProps } from './RevisionProps'
|
||||
|
||||
export class Revision extends Entity<RevisionProps> {
|
||||
get id(): UniqueEntityId {
|
||||
return this._id
|
||||
}
|
||||
|
||||
private constructor(props: RevisionProps, id?: UniqueEntityId) {
|
||||
super(props, id)
|
||||
}
|
||||
|
||||
@@ -3,10 +3,6 @@ import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
|
||||
import { RevisionMetadataProps } from './RevisionMetadataProps'
|
||||
|
||||
export class RevisionMetadata extends Entity<RevisionMetadataProps> {
|
||||
get id(): UniqueEntityId {
|
||||
return this._id
|
||||
}
|
||||
|
||||
private constructor(props: RevisionMetadataProps, id?: UniqueEntityId) {
|
||||
super(props, id)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,26 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.20.13](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.20.12...@standardnotes/scheduler-server@1.20.13) (2023-07-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.20.12](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.20.11...@standardnotes/scheduler-server@1.20.12) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.20.11](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.20.10...@standardnotes/scheduler-server@1.20.11) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.20.10](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.20.9...@standardnotes/scheduler-server@1.20.10) (2023-07-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.20.9](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.20.8...@standardnotes/scheduler-server@1.20.9) (2023-07-17)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.20.8](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.20.7...@standardnotes/scheduler-server@1.20.8) (2023-07-12)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/scheduler-server",
|
||||
"version": "1.20.8",
|
||||
"version": "1.20.13",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,26 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.21.18](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.21.17...@standardnotes/settings@1.21.18) (2023-07-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/settings
|
||||
|
||||
## [1.21.17](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.21.16...@standardnotes/settings@1.21.17) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/settings
|
||||
|
||||
## [1.21.16](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.21.15...@standardnotes/settings@1.21.16) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/settings
|
||||
|
||||
## [1.21.15](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.21.14...@standardnotes/settings@1.21.15) (2023-07-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/settings
|
||||
|
||||
## [1.21.14](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.21.13...@standardnotes/settings@1.21.14) (2023-07-17)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/settings
|
||||
|
||||
## [1.21.13](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.21.12...@standardnotes/settings@1.21.13) (2023-07-12)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/settings
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/settings",
|
||||
"version": "1.21.13",
|
||||
"version": "1.21.18",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -49,3 +49,6 @@ NEW_RELIC_LOG_LEVEL=info
|
||||
|
||||
# (Optional) Revision Dumps
|
||||
FILE_UPLOAD_PATH=
|
||||
|
||||
VALET_TOKEN_SECRET=change-me-!
|
||||
VALET_TOKEN_TTL=7200
|
||||
|
||||
@@ -3,6 +3,104 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.70.4](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.70.3...@standardnotes/syncing-server@1.70.4) (2023-07-26)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **syncing-serve:** removing other users from shared vault ([6b2389c](https://github.com/standardnotes/syncing-server-js/commit/6b2389cdc3da6d522f9ce0ba3ddff3ef1e99674f))
|
||||
|
||||
## [1.70.3](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.70.2...@standardnotes/syncing-server@1.70.3) (2023-07-26)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **syncing-server:** persisting aggregate changes from root ([#674](https://github.com/standardnotes/syncing-server-js/issues/674)) ([c34f548](https://github.com/standardnotes/syncing-server-js/commit/c34f548e45bbd8defb8d490936e90755fd284e78))
|
||||
|
||||
## [1.70.2](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.70.1...@standardnotes/syncing-server@1.70.2) (2023-07-25)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **syncing-server:** remove notifications after adding item to vault ([#672](https://github.com/standardnotes/syncing-server-js/issues/672)) ([8f88a87](https://github.com/standardnotes/syncing-server-js/commit/8f88a87c93e21f52a029167f2408ff061e2a4e93))
|
||||
|
||||
## [1.70.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.70.0...@standardnotes/syncing-server@1.70.1) (2023-07-25)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **syncing-server:** allow sender to decline the invite ([#671](https://github.com/standardnotes/syncing-server-js/issues/671)) ([46c4947](https://github.com/standardnotes/syncing-server-js/commit/46c4947871f342f0a07c68562b0e3e77e7e114d4))
|
||||
|
||||
# [1.70.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.69.0...@standardnotes/syncing-server@1.70.0) (2023-07-25)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** filtering items by shared vault permissions ([#670](https://github.com/standardnotes/syncing-server-js/issues/670)) ([5f7e768](https://github.com/standardnotes/syncing-server-js/commit/5f7e768e64da0452e6efcf70e36cb5e867291456))
|
||||
|
||||
# [1.69.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.68.4...@standardnotes/syncing-server@1.69.0) (2023-07-24)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** determin shared vault operation type ([#669](https://github.com/standardnotes/syncing-server-js/issues/669)) ([71721ab](https://github.com/standardnotes/syncing-server-js/commit/71721ab1982b65feb4c84b44b267a249b573c537))
|
||||
|
||||
## [1.68.4](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.68.3...@standardnotes/syncing-server@1.68.4) (2023-07-24)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **syncing-server:** force remove shared vault owner when removing shared vault ([f77e29d](https://github.com/standardnotes/syncing-server-js/commit/f77e29d3c9c9a28be3c5624d2c9bf0ffd6348377))
|
||||
|
||||
## [1.68.3](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.68.2...@standardnotes/syncing-server@1.68.3) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.68.2](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.68.1...@standardnotes/syncing-server@1.68.2) (2023-07-21)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* user notifications structure ([#667](https://github.com/standardnotes/syncing-server-js/issues/667)) ([1bbb639](https://github.com/standardnotes/syncing-server-js/commit/1bbb639c83922ec09e3778f85419d76669d36ae3))
|
||||
|
||||
## [1.68.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.68.0...@standardnotes/syncing-server@1.68.1) (2023-07-21)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **syncing-server:** fetching items associated with shared vaults ([#666](https://github.com/standardnotes/syncing-server-js/issues/666)) ([c030a6b](https://github.com/standardnotes/syncing-server-js/commit/c030a6b3d838b1f09593905d28ace65097a3a940))
|
||||
|
||||
# [1.68.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.67.1...@standardnotes/syncing-server@1.68.0) (2023-07-20)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** add shared vaults, invites, messages and notifications to sync response ([#665](https://github.com/standardnotes/syncing-server-js/issues/665)) ([efa4d7f](https://github.com/standardnotes/syncing-server-js/commit/efa4d7fc6007ef668e3de3b04853ac11b2d13c30))
|
||||
|
||||
## [1.67.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.67.0...@standardnotes/syncing-server@1.67.1) (2023-07-19)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add missing imports and exports for controllers ([#664](https://github.com/standardnotes/syncing-server-js/issues/664)) ([aee6e60](https://github.com/standardnotes/syncing-server-js/commit/aee6e6058359e2b5231cc13387656f837699300f))
|
||||
|
||||
# [1.67.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.66.0...@standardnotes/syncing-server@1.67.0) (2023-07-19)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **syncing-server:** add missing messages and key system identifier sql representations ([#663](https://github.com/standardnotes/syncing-server-js/issues/663)) ([d026152](https://github.com/standardnotes/syncing-server-js/commit/d026152ac8cb2ecda2eee8d3f7385d655b210938))
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** add persistence of shared vaults with users and invites + controllers ([#662](https://github.com/standardnotes/syncing-server-js/issues/662)) ([3f21a35](https://github.com/standardnotes/syncing-server-js/commit/3f21a358d24d70daf541aa62dc86cd9e29500e62))
|
||||
|
||||
# [1.66.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.65.0...@standardnotes/syncing-server@1.66.0) (2023-07-18)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** associating existing items with key systems and shared vaults ([#661](https://github.com/standardnotes/syncing-server-js/issues/661)) ([3b804e2](https://github.com/standardnotes/syncing-server-js/commit/3b804e2321f9d8444722f1d336689e12598121ca))
|
||||
|
||||
# [1.65.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.64.0...@standardnotes/syncing-server@1.65.0) (2023-07-18)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** persisting shared vault and key system associations ([#660](https://github.com/standardnotes/syncing-server-js/issues/660)) ([479d20e](https://github.com/standardnotes/syncing-server-js/commit/479d20e76f7766006dfa34a0d14401b090dec775))
|
||||
|
||||
# [1.64.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.63.1...@standardnotes/syncing-server@1.64.0) (2023-07-17)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** refactor syncing to decouple getting and saving items ([#659](https://github.com/standardnotes/syncing-server-js/issues/659)) ([cb74b23](https://github.com/standardnotes/syncing-server-js/commit/cb74b23e45b207136e299ce8a3db2c04dc87e21e))
|
||||
|
||||
## [1.63.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.63.0...@standardnotes/syncing-server@1.63.1) (2023-07-12)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
@@ -2,6 +2,10 @@ import 'reflect-metadata'
|
||||
|
||||
import '../src/Infra/InversifyExpressUtils/InversifyExpressHealthCheckController'
|
||||
import '../src/Infra/InversifyExpressUtils/InversifyExpressItemsController'
|
||||
import '../src/Infra/InversifyExpressUtils/InversifyExpressMessagesController'
|
||||
import '../src/Infra/InversifyExpressUtils/InversifyExpressSharedVaultInvitesController'
|
||||
import '../src/Infra/InversifyExpressUtils/InversifyExpressSharedVaultUsersController'
|
||||
import '../src/Infra/InversifyExpressUtils/InversifyExpressSharedVaultsController'
|
||||
|
||||
import helmet from 'helmet'
|
||||
import * as cors from 'cors'
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddNotifications1688540448427 implements MigrationInterface {
|
||||
name = 'AddNotifications1688540448427'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE `notifications` (`uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `type` varchar(36) NOT NULL, `payload` text NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `index_notifications_on_user_uuid` (`user_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX `index_notifications_on_user_uuid` ON `notifications`')
|
||||
await queryRunner.query('DROP TABLE `notifications`')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddNotifications1689671563304 implements MigrationInterface {
|
||||
name = 'AddNotifications1689671563304'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE IF NOT EXISTS `notifications` (`uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `type` varchar(36) NOT NULL, `payload` text NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `index_notifications_on_user_uuid` (`user_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX `index_notifications_on_user_uuid` ON `notifications`')
|
||||
await queryRunner.query('DROP TABLE `notifications`')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddSharedVaultAndKeySystemAssociations1689671563305 implements MigrationInterface {
|
||||
name = 'AddSharedVaultAndKeySystemAssociations1689671563305'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE `shared_vault_associations` (`uuid` varchar(36) NOT NULL, `shared_vault_uuid` varchar(36) NOT NULL, `item_uuid` varchar(36) NOT NULL, `last_edited_by` varchar(36) NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `shared_vault_uuid_on_shared_vault_associations` (`shared_vault_uuid`), INDEX `item_uuid_on_shared_vault_associations` (`item_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
|
||||
)
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE `key_system_associations` (`uuid` varchar(36) NOT NULL, `key_system_uuid` varchar(36) NOT NULL, `item_uuid` varchar(36) NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `key_system_uuid_on_key_system_associations` (`key_system_uuid`), INDEX `item_uuid_on_key_system_associations` (`item_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX `item_uuid_on_key_system_associations` ON `key_system_associations`')
|
||||
await queryRunner.query('DROP INDEX `key_system_uuid_on_key_system_associations` ON `key_system_associations`')
|
||||
await queryRunner.query('DROP TABLE `key_system_associations`')
|
||||
await queryRunner.query('DROP INDEX `item_uuid_on_shared_vault_associations` ON `shared_vault_associations`')
|
||||
await queryRunner.query(
|
||||
'DROP INDEX `shared_vault_uuid_on_shared_vault_associations` ON `shared_vault_associations`',
|
||||
)
|
||||
await queryRunner.query('DROP TABLE `shared_vault_associations`')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddSharedVaultsWithUsersAndInvites1689677728282 implements MigrationInterface {
|
||||
name = 'AddSharedVaultsWithUsersAndInvites1689677728282'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE `shared_vaults` (`uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `file_upload_bytes_used` int NOT NULL, `file_upload_bytes_limit` int NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `user_uuid_on_shared_vaults` (`user_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
|
||||
)
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE `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_shared_vault_users` (`shared_vault_uuid`), INDEX `user_uuid_on_shared_vault_users` (`user_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
|
||||
)
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE `shared_vault_invites` (`uuid` varchar(36) NOT NULL, `shared_vault_uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `sender_uuid` varchar(36) NOT NULL, `encrypted_message` text NOT NULL, `permission` varchar(24) NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `shared_vault_uuid_on_shared_vault_invites` (`shared_vault_uuid`), INDEX `user_uuid_on_shared_vault_invites` (`user_uuid`), INDEX `sender_uuid_on_shared_vault_invites` (`sender_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX `sender_uuid_on_shared_vault_invites` ON `shared_vault_invites`')
|
||||
await queryRunner.query('DROP INDEX `user_uuid_on_shared_vault_invites` ON `shared_vault_invites`')
|
||||
await queryRunner.query('DROP INDEX `shared_vault_uuid_on_shared_vault_invites` ON `shared_vault_invites`')
|
||||
await queryRunner.query('DROP TABLE `shared_vault_invites`')
|
||||
await queryRunner.query('DROP INDEX `user_uuid_on_shared_vault_users` ON `shared_vault_users`')
|
||||
await queryRunner.query('DROP INDEX `shared_vault_uuid_on_shared_vault_users` ON `shared_vault_users`')
|
||||
await queryRunner.query('DROP TABLE `shared_vault_users`')
|
||||
await queryRunner.query('DROP INDEX `user_uuid_on_shared_vaults` ON `shared_vaults`')
|
||||
await queryRunner.query('DROP TABLE `shared_vaults`')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddMessages1689745128577 implements MigrationInterface {
|
||||
name = 'AddMessages1689745128577'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE `messages` (`uuid` varchar(36) NOT NULL, `recipient_uuid` varchar(36) NOT NULL, `sender_uuid` varchar(36) NOT NULL, `encrypted_message` text NOT NULL, `replaceability_identifier` varchar(255) NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `recipient_uuid_on_messages` (`recipient_uuid`), INDEX `sender_uuid_on_messages` (`sender_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX `sender_uuid_on_messages` ON `messages`')
|
||||
await queryRunner.query('DROP INDEX `recipient_uuid_on_messages` ON `messages`')
|
||||
await queryRunner.query('DROP TABLE `messages`')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class RenameKeyMessageIdentifier1689746180559 implements MigrationInterface {
|
||||
name = 'RenameKeyMessageIdentifier1689746180559'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX `key_system_uuid_on_key_system_associations` ON `key_system_associations`')
|
||||
await queryRunner.query(
|
||||
'ALTER TABLE `key_system_associations` CHANGE `key_system_uuid` `key_system_identifier` varchar(36) NOT NULL',
|
||||
)
|
||||
await queryRunner.query(
|
||||
'CREATE INDEX `key_system_identifier_on_key_system_associations` ON `key_system_associations` (`key_system_identifier`)',
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'DROP INDEX `key_system_identifier_on_key_system_associations` ON `key_system_associations`',
|
||||
)
|
||||
await queryRunner.query(
|
||||
'ALTER TABLE `key_system_associations` CHANGE `key_system_identifier` `key_system_uuid` varchar(36) NOT NULL',
|
||||
)
|
||||
await queryRunner.query(
|
||||
'CREATE INDEX `key_system_uuid_on_key_system_associations` ON `key_system_associations` (`key_system_uuid`)',
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddNotifications1688540623272 implements MigrationInterface {
|
||||
name = 'AddNotifications1688540623272'
|
||||
export class AddNotifications1689672099828 implements MigrationInterface {
|
||||
name = 'AddNotifications1689672099828'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE "notifications" ("uuid" varchar PRIMARY KEY NOT NULL, "user_uuid" varchar(36) NOT NULL, "type" varchar(36) NOT NULL, "payload" text NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
|
||||
'CREATE TABLE IF NOT EXISTS "notifications" ("uuid" varchar PRIMARY KEY NOT NULL, "user_uuid" varchar(36) NOT NULL, "type" varchar(36) NOT NULL, "payload" text NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
|
||||
)
|
||||
await queryRunner.query('CREATE INDEX "index_notifications_on_user_uuid" ON "notifications" ("user_uuid") ')
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddSharedVaultAndKeySystemAssociations1689672099829 implements MigrationInterface {
|
||||
name = 'AddSharedVaultAndKeySystemAssociations1689672099829'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE "shared_vault_associations" ("uuid" varchar PRIMARY KEY NOT NULL, "shared_vault_uuid" varchar(36) NOT NULL, "item_uuid" varchar(36) NOT NULL, "last_edited_by" varchar(36) NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
|
||||
)
|
||||
await queryRunner.query(
|
||||
'CREATE INDEX "shared_vault_uuid_on_shared_vault_associations" ON "shared_vault_associations" ("shared_vault_uuid") ',
|
||||
)
|
||||
await queryRunner.query(
|
||||
'CREATE INDEX "item_uuid_on_shared_vault_associations" ON "shared_vault_associations" ("item_uuid") ',
|
||||
)
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE "key_system_associations" ("uuid" varchar PRIMARY KEY NOT NULL, "key_system_uuid" varchar(36) NOT NULL, "item_uuid" varchar(36) NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
|
||||
)
|
||||
await queryRunner.query(
|
||||
'CREATE INDEX "key_system_uuid_on_key_system_associations" ON "key_system_associations" ("key_system_uuid") ',
|
||||
)
|
||||
await queryRunner.query(
|
||||
'CREATE INDEX "item_uuid_on_key_system_associations" ON "key_system_associations" ("item_uuid") ',
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX "item_uuid_on_key_system_associations"')
|
||||
await queryRunner.query('DROP INDEX "key_system_uuid_on_key_system_associations"')
|
||||
await queryRunner.query('DROP TABLE "key_system_associations"')
|
||||
await queryRunner.query('DROP INDEX "item_uuid_on_shared_vault_associations"')
|
||||
await queryRunner.query('DROP INDEX "shared_vault_uuid_on_shared_vault_associations"')
|
||||
await queryRunner.query('DROP TABLE "shared_vault_associations"')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddSharedVaultsWithUsersAndInvites1689677867175 implements MigrationInterface {
|
||||
name = 'AddSharedVaultsWithUsersAndInvites1689677867175'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE "shared_vaults" ("uuid" varchar PRIMARY KEY NOT NULL, "user_uuid" varchar(36) NOT NULL, "file_upload_bytes_used" integer NOT NULL, "file_upload_bytes_limit" integer NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
|
||||
)
|
||||
await queryRunner.query('CREATE INDEX "user_uuid_on_shared_vaults" ON "shared_vaults" ("user_uuid") ')
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE "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_shared_vault_users" ON "shared_vault_users" ("shared_vault_uuid") ',
|
||||
)
|
||||
await queryRunner.query('CREATE INDEX "user_uuid_on_shared_vault_users" ON "shared_vault_users" ("user_uuid") ')
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE "shared_vault_invites" ("uuid" varchar PRIMARY KEY NOT NULL, "shared_vault_uuid" varchar(36) NOT NULL, "user_uuid" varchar(36) NOT NULL, "sender_uuid" varchar(36) NOT NULL, "encrypted_message" text 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_shared_vault_invites" ON "shared_vault_invites" ("shared_vault_uuid") ',
|
||||
)
|
||||
await queryRunner.query('CREATE INDEX "user_uuid_on_shared_vault_invites" ON "shared_vault_invites" ("user_uuid") ')
|
||||
await queryRunner.query(
|
||||
'CREATE INDEX "sender_uuid_on_shared_vault_invites" ON "shared_vault_invites" ("sender_uuid") ',
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX "sender_uuid_on_shared_vault_invites"')
|
||||
await queryRunner.query('DROP INDEX "user_uuid_on_shared_vault_invites"')
|
||||
await queryRunner.query('DROP INDEX "shared_vault_uuid_on_shared_vault_invites"')
|
||||
await queryRunner.query('DROP TABLE "shared_vault_invites"')
|
||||
await queryRunner.query('DROP INDEX "user_uuid_on_shared_vault_users"')
|
||||
await queryRunner.query('DROP INDEX "shared_vault_uuid_on_shared_vault_users"')
|
||||
await queryRunner.query('DROP TABLE "shared_vault_users"')
|
||||
await queryRunner.query('DROP INDEX "user_uuid_on_shared_vaults"')
|
||||
await queryRunner.query('DROP TABLE "shared_vaults"')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddMessages1689744778643 implements MigrationInterface {
|
||||
name = 'AddMessages1689744778643'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE "messages" ("uuid" varchar PRIMARY KEY NOT NULL, "recipient_uuid" varchar(36) NOT NULL, "sender_uuid" varchar(36) NOT NULL, "encrypted_message" text NOT NULL, "replaceability_identifier" varchar(255), "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
|
||||
)
|
||||
await queryRunner.query('CREATE INDEX "recipient_uuid_on_messages" ON "messages" ("recipient_uuid") ')
|
||||
await queryRunner.query('CREATE INDEX "sender_uuid_on_messages" ON "messages" ("sender_uuid") ')
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX "sender_uuid_on_messages"')
|
||||
await queryRunner.query('DROP INDEX "recipient_uuid_on_messages"')
|
||||
await queryRunner.query('DROP TABLE "messages"')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class RenameKeyMessageIdentifier1689746527310 implements MigrationInterface {
|
||||
name = 'RenameKeyMessageIdentifier1689746527310'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX "key_system_uuid_on_key_system_associations"')
|
||||
await queryRunner.query('DROP INDEX "item_uuid_on_key_system_associations"')
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE "temporary_key_system_associations" ("uuid" varchar PRIMARY KEY NOT NULL, "key_system_identifier" varchar(36) NOT NULL, "item_uuid" varchar(36) NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
|
||||
)
|
||||
await queryRunner.query(
|
||||
'INSERT INTO "temporary_key_system_associations"("uuid", "key_system_identifier", "item_uuid", "created_at_timestamp", "updated_at_timestamp") SELECT "uuid", "key_system_uuid", "item_uuid", "created_at_timestamp", "updated_at_timestamp" FROM "key_system_associations"',
|
||||
)
|
||||
await queryRunner.query('DROP TABLE "key_system_associations"')
|
||||
await queryRunner.query('ALTER TABLE "temporary_key_system_associations" RENAME TO "key_system_associations"')
|
||||
await queryRunner.query(
|
||||
'CREATE INDEX "item_uuid_on_key_system_associations" ON "key_system_associations" ("item_uuid") ',
|
||||
)
|
||||
await queryRunner.query(
|
||||
'CREATE INDEX "key_system_identifier_on_key_system_associations" ON "key_system_associations" ("key_system_identifier") ',
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX "key_system_identifier_on_key_system_associations"')
|
||||
await queryRunner.query('DROP INDEX "item_uuid_on_key_system_associations"')
|
||||
await queryRunner.query('ALTER TABLE "key_system_associations" RENAME TO "temporary_key_system_associations"')
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE "key_system_associations" ("uuid" varchar PRIMARY KEY NOT NULL, "key_system_uuid" varchar(36) NOT NULL, "item_uuid" varchar(36) NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
|
||||
)
|
||||
await queryRunner.query(
|
||||
'INSERT INTO "key_system_associations"("uuid", "key_system_uuid", "item_uuid", "created_at_timestamp", "updated_at_timestamp") SELECT "uuid", "key_system_identifier", "item_uuid", "created_at_timestamp", "updated_at_timestamp" FROM "temporary_key_system_associations"',
|
||||
)
|
||||
await queryRunner.query('DROP TABLE "temporary_key_system_associations"')
|
||||
await queryRunner.query(
|
||||
'CREATE INDEX "item_uuid_on_key_system_associations" ON "key_system_associations" ("item_uuid") ',
|
||||
)
|
||||
await queryRunner.query(
|
||||
'CREATE INDEX "key_system_uuid_on_key_system_associations" ON "key_system_associations" ("key_system_uuid") ',
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/syncing-server",
|
||||
"version": "1.63.1",
|
||||
"version": "1.70.4",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user