From 644c52ae36d3720dee0712e2cb826c7e617ab7b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20S=C3=B3jko?= Date: Thu, 22 Sep 2022 20:47:36 +0200 Subject: [PATCH] Revert "fix(auth): subscription token ttl" This reverts commit 6efd336f3407e7204a0c5d385ea9df5c02c7e5f5. --- .../Domain/Subscription/SubscriptionToken.ts | 2 +- .../CreateSubscriptionToken.spec.ts | 10 ++++++-- .../CreateSubscriptionToken.ts | 4 +++- .../RedisSubscriptionTokenRepository.spec.ts | 24 +++++++++++++------ .../Redis/RedisSubscriptionTokenRepository.ts | 12 +++++++--- 5 files changed, 38 insertions(+), 14 deletions(-) diff --git a/packages/auth/src/Domain/Subscription/SubscriptionToken.ts b/packages/auth/src/Domain/Subscription/SubscriptionToken.ts index b2d4c0dd5..f069483ee 100644 --- a/packages/auth/src/Domain/Subscription/SubscriptionToken.ts +++ b/packages/auth/src/Domain/Subscription/SubscriptionToken.ts @@ -1,5 +1,5 @@ export type SubscriptionToken = { userUuid: string token: string - ttl: number + expiresAt: number } diff --git a/packages/auth/src/Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken.spec.ts b/packages/auth/src/Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken.spec.ts index aa4992078..613981cc2 100644 --- a/packages/auth/src/Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken.spec.ts +++ b/packages/auth/src/Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken.spec.ts @@ -1,6 +1,7 @@ import 'reflect-metadata' import { CryptoNode } from '@standardnotes/sncrypto-node' +import { TimerInterface } from '@standardnotes/time' import { SubscriptionTokenRepositoryInterface } from '../../Subscription/SubscriptionTokenRepositoryInterface' import { CreateSubscriptionToken } from './CreateSubscriptionToken' @@ -9,9 +10,10 @@ import { Logger } from 'winston' describe('CreateSubscriptionToken', () => { let subscriptionTokenRepository: SubscriptionTokenRepositoryInterface let cryptoNode: CryptoNode + let timer: TimerInterface let logger: Logger - const createUseCase = () => new CreateSubscriptionToken(subscriptionTokenRepository, cryptoNode, logger) + const createUseCase = () => new CreateSubscriptionToken(subscriptionTokenRepository, cryptoNode, timer, logger) beforeEach(() => { subscriptionTokenRepository = {} as jest.Mocked @@ -20,6 +22,10 @@ describe('CreateSubscriptionToken', () => { cryptoNode = {} as jest.Mocked cryptoNode.generateRandomKey = jest.fn().mockReturnValueOnce('random-string') + timer = {} as jest.Mocked + timer.convertStringDateToMicroseconds = jest.fn().mockReturnValue(1) + timer.getUTCDateNHoursAhead = jest.fn().mockReturnValue(new Date(1)) + logger = {} as jest.Mocked logger.error = jest.fn() }) @@ -32,7 +38,7 @@ describe('CreateSubscriptionToken', () => { expect(subscriptionTokenRepository.save).toHaveBeenCalledWith({ userUuid: '1-2-3', token: 'random-string', - ttl: 10_800, + expiresAt: 1, }) }) diff --git a/packages/auth/src/Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken.ts b/packages/auth/src/Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken.ts index 6d3a06784..5b2492cfd 100644 --- a/packages/auth/src/Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken.ts +++ b/packages/auth/src/Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken.ts @@ -1,4 +1,5 @@ import { CryptoNode } from '@standardnotes/sncrypto-node' +import { TimerInterface } from '@standardnotes/time' import { inject, injectable } from 'inversify' import { Logger } from 'winston' @@ -14,6 +15,7 @@ export class CreateSubscriptionToken implements UseCaseInterface { @inject(TYPES.SubscriptionTokenRepository) private subscriptionTokenRepository: SubscriptionTokenRepositoryInterface, @inject(TYPES.CryptoNode) private cryptoNode: CryptoNode, + @inject(TYPES.Timer) private timer: TimerInterface, @inject(TYPES.Logger) private logger: Logger, ) {} @@ -23,7 +25,7 @@ export class CreateSubscriptionToken implements UseCaseInterface { const subscriptionToken = { userUuid: dto.userUuid, token, - ttl: 10_800, + expiresAt: this.timer.convertStringDateToMicroseconds(this.timer.getUTCDateNHoursAhead(3).toString()), } const subscriptionTokenWasSaved = await this.subscriptionTokenRepository.save(subscriptionToken) diff --git a/packages/auth/src/Infra/Redis/RedisSubscriptionTokenRepository.spec.ts b/packages/auth/src/Infra/Redis/RedisSubscriptionTokenRepository.spec.ts index a19b33b8f..c7a68790b 100644 --- a/packages/auth/src/Infra/Redis/RedisSubscriptionTokenRepository.spec.ts +++ b/packages/auth/src/Infra/Redis/RedisSubscriptionTokenRepository.spec.ts @@ -1,19 +1,25 @@ import 'reflect-metadata' import * as IORedis from 'ioredis' +import { TimerInterface } from '@standardnotes/time' import { RedisSubscriptionTokenRepository } from './RedisSubscriptionTokenRepository' import { SubscriptionToken } from '../../Domain/Subscription/SubscriptionToken' describe('RedisSubscriptionTokenRepository', () => { let redisClient: IORedis.Redis + let timer: TimerInterface - const createRepository = () => new RedisSubscriptionTokenRepository(redisClient) + const createRepository = () => new RedisSubscriptionTokenRepository(redisClient, timer) beforeEach(() => { redisClient = {} as jest.Mocked - redisClient.setex = jest.fn().mockReturnValue('OK') + redisClient.set = jest.fn().mockReturnValue('OK') redisClient.get = jest.fn() + redisClient.expireat = jest.fn().mockReturnValue(1) + + timer = {} as jest.Mocked + timer.convertMicrosecondsToSeconds = jest.fn().mockReturnValue(1) }) it('should get a user uuid in exchange for an subscription token', async () => { @@ -36,25 +42,29 @@ describe('RedisSubscriptionTokenRepository', () => { const subscriptionToken: SubscriptionToken = { userUuid: '1-2-3', token: 'random-string', - ttl: 123, + expiresAt: 123, } expect(await createRepository().save(subscriptionToken)).toBeTruthy() - expect(redisClient.setex).toHaveBeenCalledWith('subscription-token:random-string', 123, '1-2-3') + expect(redisClient.set).toHaveBeenCalledWith('subscription-token:random-string', '1-2-3') + + expect(redisClient.expireat).toHaveBeenCalledWith('subscription-token:random-string', 1) }) it('should indicate subscription token was not saved', async () => { - redisClient.setex = jest.fn().mockReturnValue(null) + redisClient.set = jest.fn().mockReturnValue(null) const subscriptionToken: SubscriptionToken = { userUuid: '1-2-3', token: 'random-string', - ttl: 123, + expiresAt: 123, } expect(await createRepository().save(subscriptionToken)).toBeFalsy() - expect(redisClient.setex).toHaveBeenCalledWith('subscription-token:random-string', 123, '1-2-3') + expect(redisClient.set).toHaveBeenCalledWith('subscription-token:random-string', '1-2-3') + + expect(redisClient.expireat).toHaveBeenCalledWith('subscription-token:random-string', 1) }) }) diff --git a/packages/auth/src/Infra/Redis/RedisSubscriptionTokenRepository.ts b/packages/auth/src/Infra/Redis/RedisSubscriptionTokenRepository.ts index 3bba3fcb8..a578edca7 100644 --- a/packages/auth/src/Infra/Redis/RedisSubscriptionTokenRepository.ts +++ b/packages/auth/src/Infra/Redis/RedisSubscriptionTokenRepository.ts @@ -4,12 +4,16 @@ import { inject, injectable } from 'inversify' import TYPES from '../../Bootstrap/Types' import { SubscriptionToken } from '../../Domain/Subscription/SubscriptionToken' import { SubscriptionTokenRepositoryInterface } from '../../Domain/Subscription/SubscriptionTokenRepositoryInterface' +import { TimerInterface } from '@standardnotes/time' @injectable() export class RedisSubscriptionTokenRepository implements SubscriptionTokenRepositoryInterface { private readonly PREFIX = 'subscription-token' - constructor(@inject(TYPES.Redis) private redisClient: IORedis.Redis) {} + constructor( + @inject(TYPES.Redis) private redisClient: IORedis.Redis, + @inject(TYPES.Timer) private timer: TimerInterface, + ) {} async getUserUuidByToken(token: string): Promise { const userUuid = await this.redisClient.get(`${this.PREFIX}:${token}`) @@ -22,9 +26,11 @@ export class RedisSubscriptionTokenRepository implements SubscriptionTokenReposi async save(subscriptionToken: SubscriptionToken): Promise { const key = `${this.PREFIX}:${subscriptionToken.token}` + const expiresAtTimestampInSeconds = this.timer.convertMicrosecondsToSeconds(subscriptionToken.expiresAt) - const wasSet = await this.redisClient.setex(key, subscriptionToken.ttl, subscriptionToken.userUuid) + const wasSet = await this.redisClient.set(key, subscriptionToken.userUuid) + const timeoutWasSet = await this.redisClient.expireat(key, expiresAtTimestampInSeconds) - return wasSet === 'OK' + return wasSet === 'OK' && timeoutWasSet !== 0 } }