Files
standardnotes-server/packages/auth/src/Domain/UseCase/CreateValetToken/CreateValetToken.spec.ts
Karol Sójko d66ae62cf4 fix: account deletion event (#904)
* fix: account deletion event

* fix: feature service binding
2023-11-07 11:34:10 +01:00

293 lines
8.9 KiB
TypeScript

import 'reflect-metadata'
import { TimerInterface } from '@standardnotes/time'
import { TokenEncoderInterface, ValetTokenData, ValetTokenOperation } from '@standardnotes/security'
import { CreateValetToken } from './CreateValetToken'
import { UserSubscription } from '../../Subscription/UserSubscription'
import { UserSubscriptionType } from '../../Subscription/UserSubscriptionType'
import { SubscriptionSettingsAssociationServiceInterface } from '../../Setting/SubscriptionSettingsAssociationServiceInterface'
import { GetRegularSubscriptionForUser } from '../GetRegularSubscriptionForUser/GetRegularSubscriptionForUser'
import { GetSubscriptionSetting } from '../GetSubscriptionSetting/GetSubscriptionSetting'
import { GetSharedSubscriptionForUser } from '../GetSharedSubscriptionForUser/GetSharedSubscriptionForUser'
import { Result, SettingName, Timestamps, Uuid } from '@standardnotes/domain-core'
import { EncryptionVersion } from '../../Encryption/EncryptionVersion'
import { SubscriptionSetting } from '../../Setting/SubscriptionSetting'
describe('CreateValetToken', () => {
let tokenEncoder: TokenEncoderInterface<ValetTokenData>
let getRegularSubscription: GetRegularSubscriptionForUser
let subscriptionSettingsAssociationService: SubscriptionSettingsAssociationServiceInterface
let getSharedSubscription: GetSharedSubscriptionForUser
let getSubscriptionSetting: GetSubscriptionSetting
let timer: TimerInterface
const valetTokenTTL = 123
let regularSubscription: UserSubscription
let sharedSubscription: UserSubscription
const createUseCase = () =>
new CreateValetToken(
tokenEncoder,
subscriptionSettingsAssociationService,
getRegularSubscription,
getSharedSubscription,
getSubscriptionSetting,
timer,
valetTokenTTL,
)
beforeEach(() => {
tokenEncoder = {} as jest.Mocked<TokenEncoderInterface<ValetTokenData>>
tokenEncoder.encodeExpirableToken = jest.fn().mockReturnValue('foobar')
getSubscriptionSetting = {} as jest.Mocked<GetSubscriptionSetting>
getSubscriptionSetting.execute = jest.fn().mockReturnValue(
Result.ok({
setting: SubscriptionSetting.create({
sensitive: false,
name: SettingName.NAMES.FileUploadBytesUsed,
value: '123',
timestamps: Timestamps.create(123456789, 123456789).getValue(),
serverEncryptionVersion: EncryptionVersion.Unencrypted,
userSubscriptionUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
}).getValue(),
}),
)
subscriptionSettingsAssociationService = {} as jest.Mocked<SubscriptionSettingsAssociationServiceInterface>
subscriptionSettingsAssociationService.getFileUploadLimit = jest.fn().mockReturnValue(5_368_709_120)
regularSubscription = {
uuid: '1-2-3',
subscriptionType: UserSubscriptionType.Regular,
userUuid: '123',
} as jest.Mocked<UserSubscription>
sharedSubscription = {
uuid: '2-3-4',
subscriptionType: UserSubscriptionType.Shared,
userUuid: '123',
} as jest.Mocked<UserSubscription>
getRegularSubscription = {} as jest.Mocked<GetRegularSubscriptionForUser>
getRegularSubscription.execute = jest.fn().mockReturnValue(Result.ok(regularSubscription))
getSharedSubscription = {} as jest.Mocked<GetSharedSubscriptionForUser>
getSharedSubscription.execute = jest.fn().mockReturnValue(Result.fail('not found'))
timer = {} as jest.Mocked<TimerInterface>
timer.getTimestampInMicroseconds = jest.fn().mockReturnValue(100)
})
it('should create a read valet token', async () => {
const response = await createUseCase().execute({
operation: ValetTokenOperation.Read,
userUuid: '1-2-3',
resources: [
{
remoteIdentifier: '1-2-3/2-3-4',
unencryptedFileSize: 123,
},
],
})
expect(response).toEqual({
success: true,
valetToken: 'foobar',
})
})
it('should not create a valet token if a user has no subscription', async () => {
getRegularSubscription.execute = jest.fn().mockReturnValue(Result.fail('not found'))
const response = await createUseCase().execute({
operation: ValetTokenOperation.Read,
userUuid: '1-2-3',
resources: [
{
remoteIdentifier: '1-2-3/2-3-4',
unencryptedFileSize: 123,
},
],
})
expect(response).toEqual({
success: false,
reason: 'no-subscription',
})
})
it('should not create a valet token if a user has an expired subscription', async () => {
regularSubscription.endsAt = 1
getRegularSubscription.execute = jest.fn().mockReturnValue(Result.ok(regularSubscription))
timer.getTimestampInMicroseconds = jest.fn().mockReturnValue(150)
const response = await createUseCase().execute({
operation: ValetTokenOperation.Read,
userUuid: '1-2-3',
resources: [
{
remoteIdentifier: '1-2-3/2-3-4',
unencryptedFileSize: 123,
},
],
})
expect(response).toEqual({
success: false,
reason: 'expired-subscription',
})
})
it('should not create a write valet token if unencrypted file size has not been provided for a resource', async () => {
const response = await createUseCase().execute({
operation: ValetTokenOperation.Write,
resources: [
{
remoteIdentifier: '2-3-4',
},
],
userUuid: '1-2-3',
})
expect(response).toEqual({
success: false,
reason: 'invalid-parameters',
})
})
it('should create a write valet token', async () => {
const response = await createUseCase().execute({
operation: ValetTokenOperation.Write,
resources: [
{
remoteIdentifier: '2-3-4',
unencryptedFileSize: 123,
},
],
userUuid: '1-2-3',
})
expect(tokenEncoder.encodeExpirableToken).toHaveBeenCalledWith(
{
sharedSubscriptionUuid: undefined,
regularSubscriptionUuid: '1-2-3',
permittedOperation: 'write',
permittedResources: [
{
remoteIdentifier: '2-3-4',
unencryptedFileSize: 123,
},
],
userUuid: '1-2-3',
uploadBytesUsed: 123,
uploadBytesLimit: 123,
},
123,
)
expect(response).toEqual({
success: true,
valetToken: 'foobar',
})
})
it('should create a write valet token for shared subscription', async () => {
getSharedSubscription.execute = jest.fn().mockReturnValue(Result.ok(sharedSubscription))
const response = await createUseCase().execute({
operation: ValetTokenOperation.Write,
resources: [
{
remoteIdentifier: '2-3-4',
unencryptedFileSize: 123,
},
],
userUuid: '1-2-3',
})
expect(tokenEncoder.encodeExpirableToken).toHaveBeenCalledWith(
{
sharedSubscriptionUuid: '2-3-4',
regularSubscriptionUuid: '1-2-3',
permittedOperation: 'write',
permittedResources: [
{
remoteIdentifier: '2-3-4',
unencryptedFileSize: 123,
},
],
userUuid: '1-2-3',
uploadBytesUsed: 123,
uploadBytesLimit: 123,
},
123,
)
expect(response).toEqual({
success: true,
valetToken: 'foobar',
})
})
it('should not create a write valet token for shared subscription if regular subscription could not be found', async () => {
getRegularSubscription.execute = jest.fn().mockReturnValue(Result.fail('not found'))
getSharedSubscription.execute = jest.fn().mockReturnValue(Result.ok(sharedSubscription))
const response = await createUseCase().execute({
operation: ValetTokenOperation.Write,
resources: [
{
remoteIdentifier: '2-3-4',
unencryptedFileSize: 123,
},
],
userUuid: '1-2-3',
})
expect(response).toEqual({
success: false,
reason: 'no-subscription',
})
})
it('should create a write valet token with default subscription upload limit if upload bytes settings do not exist', async () => {
getSubscriptionSetting.execute = jest.fn().mockReturnValue(Result.fail('not found'))
const response = await createUseCase().execute({
operation: ValetTokenOperation.Write,
userUuid: '1-2-3',
resources: [
{
remoteIdentifier: '2-3-4',
unencryptedFileSize: 123,
},
],
})
expect(tokenEncoder.encodeExpirableToken).toHaveBeenCalledWith(
{
sharedSubscriptionUuid: undefined,
regularSubscriptionUuid: '1-2-3',
permittedOperation: 'write',
permittedResources: [
{
remoteIdentifier: '2-3-4',
unencryptedFileSize: 123,
},
],
userUuid: '1-2-3',
uploadBytesUsed: 0,
uploadBytesLimit: 5368709120,
},
123,
)
expect(response).toEqual({
success: true,
valetToken: 'foobar',
})
})
})