From 398c10ce4b8e357728a8b4f354b3bf6ccc8e438d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20S=C3=B3jko?= Date: Tue, 12 Dec 2023 12:42:31 +0100 Subject: [PATCH] feat(syncing-server): add extended revisions frequency for free users (#965) --- .../Controller/GRPCWebSocketAuthMiddleware.ts | 3 +++ .../gRPC/GRPCSyncingServerServiceProxy.ts | 1 + .../syncing-server/src/Bootstrap/Container.ts | 4 +++ .../syncing-server/src/Bootstrap/Types.ts | 1 + .../Syncing/SaveItems/SaveItems.spec.ts | 13 ++++++++++ .../UseCase/Syncing/SaveItems/SaveItems.ts | 1 + .../UseCase/Syncing/SaveItems/SaveItemsDTO.ts | 1 + .../Syncing/SyncItems/SyncItems.spec.ts | 12 +++++++++ .../UseCase/Syncing/SyncItems/SyncItems.ts | 1 + .../UseCase/Syncing/SyncItems/SyncItemsDTO.ts | 1 + .../UpdateExistingItem.spec.ts | 26 +++++++++++++++++++ .../UpdateExistingItem/UpdateExistingItem.ts | 8 ++++-- .../UpdateExistingItemDTO.ts | 1 + .../Base/BaseItemsController.ts | 1 + .../InversifyExpressAuthMiddleware.ts | 3 +++ .../src/Infra/gRPC/SyncingServer.ts | 1 + 16 files changed, 76 insertions(+), 2 deletions(-) diff --git a/packages/api-gateway/src/Controller/GRPCWebSocketAuthMiddleware.ts b/packages/api-gateway/src/Controller/GRPCWebSocketAuthMiddleware.ts index 64e8af3eb..68582c7c1 100644 --- a/packages/api-gateway/src/Controller/GRPCWebSocketAuthMiddleware.ts +++ b/packages/api-gateway/src/Controller/GRPCWebSocketAuthMiddleware.ts @@ -5,6 +5,7 @@ import { BaseMiddleware } from 'inversify-express-utils' import { verify } from 'jsonwebtoken' import { Logger } from 'winston' import { ConnectionValidationResponse, IAuthClient, WebsocketConnectionAuthorizationHeader } from '@standardnotes/grpc' +import { RoleName } from '@standardnotes/domain-core' export class GRPCWebSocketAuthMiddleware extends BaseMiddleware { constructor( @@ -96,6 +97,8 @@ export class GRPCWebSocketAuthMiddleware extends BaseMiddleware { response.locals.user = decodedToken.user response.locals.session = decodedToken.session response.locals.roles = decodedToken.roles + response.locals.isFreeUser = + decodedToken.roles.length === 1 && decodedToken.roles[0].name === RoleName.NAMES.CoreUser } catch (error) { this.logger.error( `Could not pass the request to websocket connection validation on underlying service: ${ diff --git a/packages/api-gateway/src/Service/gRPC/GRPCSyncingServerServiceProxy.ts b/packages/api-gateway/src/Service/gRPC/GRPCSyncingServerServiceProxy.ts index 84a15f301..c786fe8b9 100644 --- a/packages/api-gateway/src/Service/gRPC/GRPCSyncingServerServiceProxy.ts +++ b/packages/api-gateway/src/Service/gRPC/GRPCSyncingServerServiceProxy.ts @@ -31,6 +31,7 @@ export class GRPCSyncingServerServiceProxy { if (response.locals.session) { metadata.set('x-session-uuid', response.locals.session.uuid) } + metadata.set('x-is-free-user', response.locals.isFreeUser ? 'true' : 'false') this.syncingClient.syncItems(syncRequest, metadata, (error, syncResponse) => { if (error) { diff --git a/packages/syncing-server/src/Bootstrap/Container.ts b/packages/syncing-server/src/Bootstrap/Container.ts index d33e27e9d..c5dc7ec2e 100644 --- a/packages/syncing-server/src/Bootstrap/Container.ts +++ b/packages/syncing-server/src/Bootstrap/Container.ts @@ -458,6 +458,9 @@ export class ContainerConfigLoader { container .bind(TYPES.Sync_REVISIONS_FREQUENCY) .toConstantValue(env.get('REVISIONS_FREQUENCY', true) ? +env.get('REVISIONS_FREQUENCY', true) : 300) + container + .bind(TYPES.Sync_FREE_REVISIONS_FREQUENCY) + .toConstantValue(env.get('FREE_REVISIONS_FREQUENCY', true) ? +env.get('FREE_REVISIONS_FREQUENCY', true) : 86_400) container.bind(TYPES.Sync_VERSION).toConstantValue(env.get('VERSION', true) ?? 'development') container .bind(TYPES.Sync_CONTENT_SIZE_TRANSFER_LIMIT) @@ -601,6 +604,7 @@ export class ContainerConfigLoader { container.get(TYPES.Sync_Timer), container.get(TYPES.Sync_DomainEventPublisher), container.get(TYPES.Sync_DomainEventFactory), + container.get(TYPES.Sync_FREE_REVISIONS_FREQUENCY), container.get(TYPES.Sync_REVISIONS_FREQUENCY), container.get(TYPES.Sync_DetermineSharedVaultOperationOnItem), container.get(TYPES.Sync_AddNotificationsForUsers), diff --git a/packages/syncing-server/src/Bootstrap/Types.ts b/packages/syncing-server/src/Bootstrap/Types.ts index 846eb186e..a96d327cc 100644 --- a/packages/syncing-server/src/Bootstrap/Types.ts +++ b/packages/syncing-server/src/Bootstrap/Types.ts @@ -34,6 +34,7 @@ const TYPES = { Sync_S3_BACKUP_BUCKET_NAME: Symbol.for('Sync_S3_BACKUP_BUCKET_NAME'), Sync_EMAIL_ATTACHMENT_MAX_BYTE_SIZE: Symbol.for('Sync_EMAIL_ATTACHMENT_MAX_BYTE_SIZE'), Sync_REVISIONS_FREQUENCY: Symbol.for('Sync_REVISIONS_FREQUENCY'), + Sync_FREE_REVISIONS_FREQUENCY: Symbol.for('Sync_FREE_REVISIONS_FREQUENCY'), Sync_VERSION: Symbol.for('Sync_VERSION'), Sync_CONTENT_SIZE_TRANSFER_LIMIT: Symbol.for('Sync_CONTENT_SIZE_TRANSFER_LIMIT'), Sync_MAX_ITEMS_LIMIT: Symbol.for('Sync_MAX_ITEMS_LIMIT'), diff --git a/packages/syncing-server/src/Domain/UseCase/Syncing/SaveItems/SaveItems.spec.ts b/packages/syncing-server/src/Domain/UseCase/Syncing/SaveItems/SaveItems.spec.ts index 038d278e9..5a74dc780 100644 --- a/packages/syncing-server/src/Domain/UseCase/Syncing/SaveItems/SaveItems.spec.ts +++ b/packages/syncing-server/src/Domain/UseCase/Syncing/SaveItems/SaveItems.spec.ts @@ -113,6 +113,7 @@ describe('SaveItems', () => { readOnlyAccess: false, sessionUuid: 'session-uuid', snjsVersion: '2.200.0', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() @@ -137,6 +138,7 @@ describe('SaveItems', () => { readOnlyAccess: false, sessionUuid: 'session-uuid', snjsVersion: '2.200.0', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() @@ -161,6 +163,7 @@ describe('SaveItems', () => { readOnlyAccess: false, sessionUuid: 'session-uuid', snjsVersion: '2.200.0', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() @@ -182,6 +185,7 @@ describe('SaveItems', () => { readOnlyAccess: true, sessionUuid: 'session-uuid', snjsVersion: '2.200.0', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() @@ -204,6 +208,7 @@ describe('SaveItems', () => { readOnlyAccess: false, sessionUuid: 'session-uuid', snjsVersion: '2.200.0', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() @@ -222,6 +227,7 @@ describe('SaveItems', () => { readOnlyAccess: false, sessionUuid: 'session-uuid', snjsVersion: '2.200.0', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() @@ -240,10 +246,12 @@ describe('SaveItems', () => { readOnlyAccess: false, sessionUuid: 'session-uuid', snjsVersion: '2.200.0', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() expect(updateExistingItem.execute).toHaveBeenCalledWith({ + isFreeUser: false, itemHash: itemHash1, existingItem: savedItem, sessionUuid: 'session-uuid', @@ -284,10 +292,12 @@ describe('SaveItems', () => { readOnlyAccess: false, sessionUuid: 'session-uuid', snjsVersion: '2.200.0', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() expect(updateExistingItem.execute).toHaveBeenCalledWith({ + isFreeUser: false, itemHash: itemHash1, existingItem: savedItem, sessionUuid: 'session-uuid', @@ -310,6 +320,7 @@ describe('SaveItems', () => { readOnlyAccess: false, sessionUuid: 'session-uuid', snjsVersion: '2.200.0', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() @@ -334,6 +345,7 @@ describe('SaveItems', () => { readOnlyAccess: false, sessionUuid: 'session-uuid', snjsVersion: '2.200.0', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() @@ -379,6 +391,7 @@ describe('SaveItems', () => { readOnlyAccess: false, sessionUuid: 'session-uuid', snjsVersion: '2.200.0', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() diff --git a/packages/syncing-server/src/Domain/UseCase/Syncing/SaveItems/SaveItems.ts b/packages/syncing-server/src/Domain/UseCase/Syncing/SaveItems/SaveItems.ts index bb13d1e0c..ec81d1059 100644 --- a/packages/syncing-server/src/Domain/UseCase/Syncing/SaveItems/SaveItems.ts +++ b/packages/syncing-server/src/Domain/UseCase/Syncing/SaveItems/SaveItems.ts @@ -84,6 +84,7 @@ export class SaveItems implements UseCaseInterface { itemHash, sessionUuid: dto.sessionUuid, performingUserUuid: dto.userUuid, + isFreeUser: dto.isFreeUser, }) if (udpatedItemOrError.isFailed()) { this.logger.error( diff --git a/packages/syncing-server/src/Domain/UseCase/Syncing/SaveItems/SaveItemsDTO.ts b/packages/syncing-server/src/Domain/UseCase/Syncing/SaveItems/SaveItemsDTO.ts index 3e6938bb9..205e11d60 100644 --- a/packages/syncing-server/src/Domain/UseCase/Syncing/SaveItems/SaveItemsDTO.ts +++ b/packages/syncing-server/src/Domain/UseCase/Syncing/SaveItems/SaveItemsDTO.ts @@ -7,4 +7,5 @@ export interface SaveItemsDTO { readOnlyAccess: boolean sessionUuid: string | null snjsVersion: string + isFreeUser: boolean } diff --git a/packages/syncing-server/src/Domain/UseCase/Syncing/SyncItems/SyncItems.spec.ts b/packages/syncing-server/src/Domain/UseCase/Syncing/SyncItems/SyncItems.spec.ts index d616686bc..254ad5f7d 100644 --- a/packages/syncing-server/src/Domain/UseCase/Syncing/SyncItems/SyncItems.spec.ts +++ b/packages/syncing-server/src/Domain/UseCase/Syncing/SyncItems/SyncItems.spec.ts @@ -156,6 +156,7 @@ describe('SyncItems', () => { apiVersion: ApiVersion.v20200115, sessionUuid: null, snjsVersion: '1.2.3', + isFreeUser: false, }) expect(result.getValue()).toEqual({ conflicts: [], @@ -181,6 +182,7 @@ describe('SyncItems', () => { userUuid: '1-2-3', apiVersion: '20200115', snjsVersion: '1.2.3', + isFreeUser: false, readOnlyAccess: false, sessionUuid: null, }) @@ -205,6 +207,7 @@ describe('SyncItems', () => { apiVersion: ApiVersion.v20200115, sessionUuid: null, snjsVersion: '1.2.3', + isFreeUser: false, }) } catch (error) { caughtError = error @@ -224,6 +227,7 @@ describe('SyncItems', () => { contentType: 'Note', apiVersion: ApiVersion.v20200115, snjsVersion: '1.2.3', + isFreeUser: false, }) expect(result.getValue()).toEqual({ conflicts: [], @@ -249,6 +253,7 @@ describe('SyncItems', () => { contentType: 'Note', apiVersion: ApiVersion.v20200115, snjsVersion: '1.2.3', + isFreeUser: false, sharedVaultUuids: ['00000000-0000-0000-0000-000000000000'], }) expect(result.getValue()).toEqual({ @@ -301,6 +306,7 @@ describe('SyncItems', () => { contentType: 'Note', apiVersion: ApiVersion.v20200115, snjsVersion: '1.2.3', + isFreeUser: false, }) expect(result.getValue()).toEqual({ @@ -340,6 +346,7 @@ describe('SyncItems', () => { contentType: 'Note', apiVersion: ApiVersion.v20200115, snjsVersion: '1.2.3', + isFreeUser: false, }) expect(result.isFailed()).toBeTruthy() @@ -360,6 +367,7 @@ describe('SyncItems', () => { contentType: 'Note', apiVersion: ApiVersion.v20200115, snjsVersion: '1.2.3', + isFreeUser: false, }) expect(result.isFailed()).toBeTruthy() @@ -380,6 +388,7 @@ describe('SyncItems', () => { contentType: 'Note', apiVersion: ApiVersion.v20200115, snjsVersion: '1.2.3', + isFreeUser: false, }) expect(result.isFailed()).toBeTruthy() @@ -400,6 +409,7 @@ describe('SyncItems', () => { contentType: 'Note', apiVersion: ApiVersion.v20200115, snjsVersion: '1.2.3', + isFreeUser: false, }) expect(result.isFailed()).toBeTruthy() @@ -420,6 +430,7 @@ describe('SyncItems', () => { contentType: 'Note', apiVersion: ApiVersion.v20200115, snjsVersion: '1.2.3', + isFreeUser: false, }) expect(result.isFailed()).toBeTruthy() @@ -440,6 +451,7 @@ describe('SyncItems', () => { contentType: 'Note', apiVersion: ApiVersion.v20200115, snjsVersion: '1.2.3', + isFreeUser: false, }) expect(result.isFailed()).toBeTruthy() diff --git a/packages/syncing-server/src/Domain/UseCase/Syncing/SyncItems/SyncItems.ts b/packages/syncing-server/src/Domain/UseCase/Syncing/SyncItems/SyncItems.ts index 725d282f4..320d2dfb4 100644 --- a/packages/syncing-server/src/Domain/UseCase/Syncing/SyncItems/SyncItems.ts +++ b/packages/syncing-server/src/Domain/UseCase/Syncing/SyncItems/SyncItems.ts @@ -47,6 +47,7 @@ export class SyncItems implements UseCaseInterface { readOnlyAccess: dto.readOnlyAccess, sessionUuid: dto.sessionUuid, snjsVersion: dto.snjsVersion, + isFreeUser: dto.isFreeUser, }) if (saveItemsResultOrError.isFailed()) { return Result.fail(saveItemsResultOrError.getError()) diff --git a/packages/syncing-server/src/Domain/UseCase/Syncing/SyncItems/SyncItemsDTO.ts b/packages/syncing-server/src/Domain/UseCase/Syncing/SyncItems/SyncItemsDTO.ts index ddba8ae6e..d81da6c1c 100644 --- a/packages/syncing-server/src/Domain/UseCase/Syncing/SyncItems/SyncItemsDTO.ts +++ b/packages/syncing-server/src/Domain/UseCase/Syncing/SyncItems/SyncItemsDTO.ts @@ -13,4 +13,5 @@ export type SyncItemsDTO = { snjsVersion: string readOnlyAccess: boolean sessionUuid: string | null + isFreeUser: boolean } diff --git a/packages/syncing-server/src/Domain/UseCase/Syncing/UpdateExistingItem/UpdateExistingItem.spec.ts b/packages/syncing-server/src/Domain/UseCase/Syncing/UpdateExistingItem/UpdateExistingItem.spec.ts index bc5be9ad6..c98a6a0e7 100644 --- a/packages/syncing-server/src/Domain/UseCase/Syncing/UpdateExistingItem/UpdateExistingItem.spec.ts +++ b/packages/syncing-server/src/Domain/UseCase/Syncing/UpdateExistingItem/UpdateExistingItem.spec.ts @@ -38,6 +38,7 @@ describe('UpdateExistingItem', () => { timer, domainEventPublisher, domainEventFactory, + 86_400, 5, determineSharedVaultOperationOnItem, addNotificationsForUsers, @@ -137,6 +138,7 @@ describe('UpdateExistingItem', () => { itemHash: itemHash1, sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() @@ -151,6 +153,7 @@ describe('UpdateExistingItem', () => { itemHash: itemHash1, sessionUuid: 'invalid-uuid', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeTruthy() @@ -167,6 +170,7 @@ describe('UpdateExistingItem', () => { }).getValue(), sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeTruthy() @@ -183,6 +187,7 @@ describe('UpdateExistingItem', () => { }).getValue(), sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() @@ -206,6 +211,7 @@ describe('UpdateExistingItem', () => { }).getValue(), sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() @@ -224,6 +230,7 @@ describe('UpdateExistingItem', () => { }).getValue(), sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeTruthy() @@ -241,6 +248,7 @@ describe('UpdateExistingItem', () => { }).getValue(), sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() @@ -260,6 +268,7 @@ describe('UpdateExistingItem', () => { }).getValue(), sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() @@ -280,6 +289,7 @@ describe('UpdateExistingItem', () => { }).getValue(), sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() @@ -300,6 +310,7 @@ describe('UpdateExistingItem', () => { }).getValue(), sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() @@ -323,6 +334,7 @@ describe('UpdateExistingItem', () => { }).getValue(), sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeTruthy() @@ -347,6 +359,7 @@ describe('UpdateExistingItem', () => { }).getValue(), sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeTruthy() @@ -361,6 +374,7 @@ describe('UpdateExistingItem', () => { itemHash: itemHash1, sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: 'invalid-uuid', + isFreeUser: false, }) expect(result.isFailed()).toBeTruthy() }) @@ -379,6 +393,7 @@ describe('UpdateExistingItem', () => { itemHash, sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() expect(item1.props.sharedVaultAssociation).not.toBeUndefined() @@ -405,6 +420,7 @@ describe('UpdateExistingItem', () => { itemHash, sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() @@ -442,6 +458,7 @@ describe('UpdateExistingItem', () => { itemHash, sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() @@ -470,6 +487,7 @@ describe('UpdateExistingItem', () => { itemHash, sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeTruthy() mock.mockRestore() @@ -490,6 +508,7 @@ describe('UpdateExistingItem', () => { itemHash, sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeTruthy() }) @@ -521,6 +540,7 @@ describe('UpdateExistingItem', () => { itemHash, sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeTruthy() }) @@ -555,6 +575,7 @@ describe('UpdateExistingItem', () => { itemHash, sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeTruthy() @@ -576,6 +597,7 @@ describe('UpdateExistingItem', () => { itemHash, sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeTruthy() }) @@ -595,6 +617,7 @@ describe('UpdateExistingItem', () => { itemHash, sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() expect(item1.props.keySystemAssociation).not.toBeUndefined() @@ -616,6 +639,7 @@ describe('UpdateExistingItem', () => { itemHash, sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeFalsy() @@ -636,6 +660,7 @@ describe('UpdateExistingItem', () => { itemHash, sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeTruthy() }) @@ -658,6 +683,7 @@ describe('UpdateExistingItem', () => { itemHash, sessionUuid: '00000000-0000-0000-0000-000000000000', performingUserUuid: '00000000-0000-0000-0000-000000000000', + isFreeUser: false, }) expect(result.isFailed()).toBeTruthy() mock.mockRestore() diff --git a/packages/syncing-server/src/Domain/UseCase/Syncing/UpdateExistingItem/UpdateExistingItem.ts b/packages/syncing-server/src/Domain/UseCase/Syncing/UpdateExistingItem/UpdateExistingItem.ts index db7cafcca..2aed2732d 100644 --- a/packages/syncing-server/src/Domain/UseCase/Syncing/UpdateExistingItem/UpdateExistingItem.ts +++ b/packages/syncing-server/src/Domain/UseCase/Syncing/UpdateExistingItem/UpdateExistingItem.ts @@ -31,7 +31,8 @@ export class UpdateExistingItem implements UseCaseInterface { private timer: TimerInterface, private domainEventPublisher: DomainEventPublisherInterface, private domainEventFactory: DomainEventFactoryInterface, - private revisionFrequency: number, + private freeRevisionFrequency: number, + private premiumRevisionFrequency: number, private determineSharedVaultOperationOnItem: DetermineSharedVaultOperationOnItem, private addNotificationForUsers: AddNotificationsForUsers, private removeNotificationsForUser: RemoveNotificationsForUser, @@ -169,7 +170,10 @@ export class UpdateExistingItem implements UseCaseInterface { await this.itemRepository.update(dto.existingItem) - if (secondsFromLastUpdate >= this.revisionFrequency) { + /* istanbul ignore next */ + const revisionsFrequency = dto.isFreeUser ? this.freeRevisionFrequency : this.premiumRevisionFrequency + + if (secondsFromLastUpdate >= revisionsFrequency) { if ( dto.existingItem.props.contentType.value !== null && [ContentType.TYPES.Note, ContentType.TYPES.File].includes(dto.existingItem.props.contentType.value) diff --git a/packages/syncing-server/src/Domain/UseCase/Syncing/UpdateExistingItem/UpdateExistingItemDTO.ts b/packages/syncing-server/src/Domain/UseCase/Syncing/UpdateExistingItem/UpdateExistingItemDTO.ts index ad2c1de20..52e431d50 100644 --- a/packages/syncing-server/src/Domain/UseCase/Syncing/UpdateExistingItem/UpdateExistingItemDTO.ts +++ b/packages/syncing-server/src/Domain/UseCase/Syncing/UpdateExistingItem/UpdateExistingItemDTO.ts @@ -6,4 +6,5 @@ export interface UpdateExistingItemDTO { itemHash: ItemHash sessionUuid: string | null performingUserUuid: string + isFreeUser: boolean } diff --git a/packages/syncing-server/src/Infra/InversifyExpressUtils/Base/BaseItemsController.ts b/packages/syncing-server/src/Infra/InversifyExpressUtils/Base/BaseItemsController.ts index e623d0010..3ea6f4147 100644 --- a/packages/syncing-server/src/Infra/InversifyExpressUtils/Base/BaseItemsController.ts +++ b/packages/syncing-server/src/Infra/InversifyExpressUtils/Base/BaseItemsController.ts @@ -70,6 +70,7 @@ export class BaseItemsController extends BaseHttpController { readOnlyAccess: response.locals.readOnlyAccess, sessionUuid: response.locals.session ? response.locals.session.uuid : null, sharedVaultUuids, + isFreeUser: response.locals.isFreeUser, }) if (syncResult.isFailed()) { return this.json({ error: { message: syncResult.getError() } }, HttpStatusCode.BadRequest) diff --git a/packages/syncing-server/src/Infra/InversifyExpressUtils/Middleware/InversifyExpressAuthMiddleware.ts b/packages/syncing-server/src/Infra/InversifyExpressUtils/Middleware/InversifyExpressAuthMiddleware.ts index 954135acb..54b2bca4e 100644 --- a/packages/syncing-server/src/Infra/InversifyExpressUtils/Middleware/InversifyExpressAuthMiddleware.ts +++ b/packages/syncing-server/src/Infra/InversifyExpressUtils/Middleware/InversifyExpressAuthMiddleware.ts @@ -3,6 +3,7 @@ import { BaseMiddleware } from 'inversify-express-utils' import { verify } from 'jsonwebtoken' import { CrossServiceTokenData } from '@standardnotes/security' import * as winston from 'winston' +import { RoleName } from '@standardnotes/domain-core' export class InversifyExpressAuthMiddleware extends BaseMiddleware { constructor( @@ -26,6 +27,8 @@ export class InversifyExpressAuthMiddleware extends BaseMiddleware { response.locals.user = decodedToken.user response.locals.roles = decodedToken.roles + response.locals.isFreeUser = + decodedToken.roles.length === 1 && decodedToken.roles[0].name === RoleName.NAMES.CoreUser response.locals.session = decodedToken.session response.locals.readOnlyAccess = decodedToken.session?.readonly_access ?? false response.locals.sharedVaultOwnerContext = decodedToken.shared_vault_owner_context diff --git a/packages/syncing-server/src/Infra/gRPC/SyncingServer.ts b/packages/syncing-server/src/Infra/gRPC/SyncingServer.ts index 9fd6bf8d1..395b6ffc2 100644 --- a/packages/syncing-server/src/Infra/gRPC/SyncingServer.ts +++ b/packages/syncing-server/src/Infra/gRPC/SyncingServer.ts @@ -88,6 +88,7 @@ export class SyncingServer implements ISyncingServer { readOnlyAccess: call.metadata.get('x-read-only-access').pop() === 'true', sessionUuid: call.metadata.get('x-session-uuid').pop() as string, sharedVaultUuids, + isFreeUser: call.metadata.get('x-is-free-user').pop() === 'true', }) if (syncResult.isFailed()) { const metadata = new grpc.Metadata()