mirror of
https://github.com/standardnotes/server
synced 2026-01-16 20:04:32 -05:00
293 lines
8.9 KiB
TypeScript
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',
|
|
})
|
|
})
|
|
})
|