From 637486a69c9846fb0122d8c658e677c4fea4fdc5 Mon Sep 17 00:00:00 2001 From: Xavier Abad <77491413+xabg2@users.noreply.github.com> Date: Fri, 16 Jan 2026 16:30:42 +0100 Subject: [PATCH] feat: use Logger instead of passing it as prop --- src/app.ts | 14 ++--- src/cli/determine-lifetime-user.ts | 9 +--- src/server.ts | 6 +-- src/services/tiers.service.ts | 17 +++---- .../invoices/InvoiceCompletedHandler.ts | 8 +-- src/webhooks/handleDisputeResult.ts | 37 ++++---------- src/webhooks/handleLifetimeRefunded.ts | 12 ++--- src/webhooks/handleSubscriptionCanceled.ts | 25 ++++----- src/webhooks/index.ts | 51 +++++++++++-------- src/webhooks/providers/bit2me/index.ts | 3 +- src/webhooks/utils/handleCancelPlan.ts | 18 ++++--- tests/src/helpers/services-factory.ts | 2 - tests/src/services/tiers.service.test.ts | 18 +++---- .../invoices/InvoiceCompletedHandler.test.ts | 3 -- .../src/webhooks/handleDisputeResult.test.ts | 12 +---- .../webhooks/handleLifetimeRefunded.test.ts | 20 +------- .../handleSubscriptionCanceled.test.ts | 8 --- .../webhooks/utils/handleCancelPlan.test.ts | 14 ++--- 18 files changed, 96 insertions(+), 181 deletions(-) diff --git a/src/app.ts b/src/app.ts index 71d58a58..a70a0b79 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,4 +1,3 @@ -import Stripe from 'stripe'; import fastifyCors from '@fastify/cors'; import Fastify, { FastifyInstance } from 'fastify'; import { AppConfig } from './config'; @@ -13,8 +12,8 @@ import CacheService from './services/cache.service'; import { PaymentService } from './services/payment.service'; import { StorageService } from './services/storage.service'; import { UsersService } from './services/users.service'; -import webhook from './webhooks'; -import cryptoWebhook from './webhooks/providers/bit2me/index'; +import { providerWebhooksEvents } from './webhooks'; +import { cryptoProviderWebhooks } from './webhooks/providers/bit2me/index'; import { LicenseCodesService } from './services/licenseCodes.service'; import { ObjectStorageService } from './services/objectStorage.service'; import { TiersService } from './services/tiers.service'; @@ -34,7 +33,6 @@ interface AppDependencies { objectStorageService: ObjectStorageService; productsService: ProductsService; userFeaturesOverridesService: UserFeaturesOverridesService; - stripe: Stripe; config: AppConfig; } @@ -48,7 +46,6 @@ export async function buildApp({ objectStorageService, productsService, userFeaturesOverridesService, - stripe, config, }: AppDependencies): Promise { const fastify = Fastify({ @@ -81,8 +78,7 @@ export async function buildApp({ fastify.register(controllerMigration(paymentService, usersService, config)); fastify.register( - webhook( - stripe, + providerWebhooksEvents({ storageService, usersService, paymentService, @@ -90,11 +86,11 @@ export async function buildApp({ cacheService, objectStorageService, tiersService, - ), + }), ); fastify.register( - cryptoWebhook({ + cryptoProviderWebhooks({ storageService, usersService, paymentService, diff --git a/src/cli/determine-lifetime-user.ts b/src/cli/determine-lifetime-user.ts index f0b1e826..a5346dfe 100644 --- a/src/cli/determine-lifetime-user.ts +++ b/src/cli/determine-lifetime-user.ts @@ -58,14 +58,7 @@ async function main() { const usersTiersRepository = new MongoDBUsersTiersRepository(mongoClient); const storageService = new StorageService(envVariablesConfig, axios); - const tiersService = new TiersService( - usersService, - paymentService, - tiersRepository, - usersTiersRepository, - storageService, - envVariablesConfig, - ); + const tiersService = new TiersService(usersService, tiersRepository, usersTiersRepository, storageService); const determineLifetimeUserCondition = new DetermineLifetimeConditions(paymentService, tiersService); const user = await usersService.findUserByCustomerID(customerId); diff --git a/src/server.ts b/src/server.ts index f813bd55..9e5b106e 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,6 +1,5 @@ import axios from 'axios'; import { MongoClient } from 'mongodb'; -import Stripe from 'stripe'; import { FastifyInstance } from 'fastify'; import { StorageService } from './services/storage.service'; @@ -35,6 +34,7 @@ import { MongoDBUserFeatureOverridesRepository, UserFeatureOverridesRepository, } from './core/users/MongoDBUserFeatureOverridesRepository'; +import { stripePaymentsAdapter } from './infrastructure/adapters/stripe.adapter'; const start = async (mongoTestClient?: MongoClient): Promise => { const mongoClient = mongoTestClient ?? (await new MongoClient(envVariablesConfig.MONGO_URI).connect()); @@ -50,9 +50,8 @@ const start = async (mongoTestClient?: MongoClient): Promise => mongoClient, ); - const stripe = new Stripe(envVariablesConfig.STRIPE_SECRET_KEY, { apiVersion: '2025-02-24.acacia' }); const bit2MeService = new Bit2MeService(envVariablesConfig, axios); - const paymentService = new PaymentService(stripe, productsRepository, bit2MeService); + const paymentService = new PaymentService(stripePaymentsAdapter.getInstance(), productsRepository, bit2MeService); const storageService = new StorageService(envVariablesConfig, axios); const usersService = new UsersService( usersRepository, @@ -84,7 +83,6 @@ const start = async (mongoTestClient?: MongoClient): Promise => objectStorageService, productsService, userFeaturesOverridesService, - stripe, config: envVariablesConfig, }); diff --git a/src/services/tiers.service.ts b/src/services/tiers.service.ts index 982e82a6..05669223 100644 --- a/src/services/tiers.service.ts +++ b/src/services/tiers.service.ts @@ -5,9 +5,9 @@ import { StorageService } from './storage.service'; import { Service, Tier } from '../core/users/Tier'; import { UsersTiersRepository } from '../core/users/MongoDBUsersTiersRepository'; import Stripe from 'stripe'; -import { FastifyBaseLogger } from 'fastify'; import axios, { isAxiosError } from 'axios'; import { Customer } from '../infrastructure/domain/entities/customer'; +import Logger from '../Logger'; export class TierNotFoundError extends Error { constructor(message: string) { @@ -99,7 +99,7 @@ export class TiersService { return tier; } - async removeTier(userWithEmail: User & { email: string }, productId: string, log: FastifyBaseLogger): Promise { + async removeTier(userWithEmail: User & { email: string }, productId: string): Promise { const tier = await this.tiersRepository.findByProductId({ productId }); const { uuid: userUuid } = userWithEmail; @@ -116,7 +116,7 @@ export class TiersService { switch (s) { case Service.Drive: - await this.removeDriveFeatures(userUuid, tier, log); + await this.removeDriveFeatures(userUuid, tier); break; case Service.Vpn: await this.removeVPNFeatures(userUuid, tier.featuresPerService['vpn']); @@ -133,7 +133,6 @@ export class TiersService { customer: Customer, subscriptionSeats: Stripe.InvoiceLineItem['quantity'], tier: Tier, - log: FastifyBaseLogger, customMaxSpaceBytes?: number, ): Promise { const features = tier.featuresPerService[Service.Drive]; @@ -154,10 +153,10 @@ export class TiersService { seats: subscriptionSeats, tierId: driveTierId, }); - log.info(`[DRIVE/WORKSPACES]: The workspace for user ${userWithEmail.uuid} has been updated`); + Logger.info(`[DRIVE/WORKSPACES]: The workspace for user ${userWithEmail.uuid} has been updated`); } catch (err) { if (isAxiosError(err) && err.response?.status === 404) { - log.info( + Logger.info( `[DRIVE/WORKSPACES]: User with customer Id: ${customer.id} - uuid: ${userWithEmail.uuid} - email: ${customer.email} does not have a workspace. Creating a new one...`, ); await this.usersService.initializeWorkspace(userWithEmail.uuid, { @@ -184,7 +183,7 @@ export class TiersService { ); } - async removeDriveFeatures(userUuid: User['uuid'], tier: Tier, log: FastifyBaseLogger): Promise { + async removeDriveFeatures(userUuid: User['uuid'], tier: Tier): Promise { const freeTier = await this.getTierProductsByProductsId('free'); const features = tier.featuresPerService[Service.Drive]; @@ -195,12 +194,12 @@ export class TiersService { } catch (error) { if (axios.isAxiosError(error) && error.response) { const { status, data } = error.response; - log.error( + Logger.error( `Failed to delete workspace for user ${userUuid}. Status: ${status}, Response: ${JSON.stringify(data)}`, ); throw data; } else { - log.error(`Unexpected error deleting workspace for user ${userUuid}: ${error}`); + Logger.error(`Unexpected error deleting workspace for user ${userUuid}: ${error}`); throw error; } } diff --git a/src/webhooks/events/invoices/InvoiceCompletedHandler.ts b/src/webhooks/events/invoices/InvoiceCompletedHandler.ts index 060a1a03..4e81a12d 100644 --- a/src/webhooks/events/invoices/InvoiceCompletedHandler.ts +++ b/src/webhooks/events/invoices/InvoiceCompletedHandler.ts @@ -1,6 +1,5 @@ import Stripe from 'stripe'; import { DetermineLifetimeConditions } from '../../../core/users/DetermineLifetimeConditions'; -import { FastifyBaseLogger } from 'fastify'; import { PaymentService } from '../../../services/payment.service'; import { PriceMetadata } from '../../../types/stripe'; import { User, UserType } from '../../../core/users/User'; @@ -23,7 +22,6 @@ export interface InvoiceCompletedHandlerPayload { } export class InvoiceCompletedHandler { - private readonly logger: FastifyBaseLogger; private readonly determineLifetimeConditions: DetermineLifetimeConditions; private readonly objectStorageWebhookHandler: ObjectStorageWebhookHandler; private readonly paymentService: PaymentService; @@ -33,7 +31,6 @@ export class InvoiceCompletedHandler { private readonly cacheService: CacheService; constructor({ - logger, determineLifetimeConditions, objectStorageWebhookHandler, paymentService, @@ -42,7 +39,6 @@ export class InvoiceCompletedHandler { usersService, cacheService, }: { - logger: FastifyBaseLogger; determineLifetimeConditions: DetermineLifetimeConditions; objectStorageWebhookHandler: ObjectStorageWebhookHandler; paymentService: PaymentService; @@ -51,7 +47,6 @@ export class InvoiceCompletedHandler { usersService: UsersService; cacheService: CacheService; }) { - this.logger = logger; this.determineLifetimeConditions = determineLifetimeConditions; this.objectStorageWebhookHandler = objectStorageWebhookHandler; this.paymentService = paymentService; @@ -133,7 +128,7 @@ export class InvoiceCompletedHandler { const localUser = await this.usersService.findUserByUuid(userUuid); await this.handleNewProduct({ - user: { ...localUser, email: email as string }, + user: { ...localUser, email: email }, isLifetimePlan, productId, customer, @@ -344,7 +339,6 @@ export class InvoiceCompletedHandler { customer, totalQuantity, tierToApply, - this.logger, lifetimeMaxSpaceBytesToApply, ); Logger.info(`Drive features applied for user ${user.uuid} with customerId ${customer.id}`); diff --git a/src/webhooks/handleDisputeResult.ts b/src/webhooks/handleDisputeResult.ts index 33cea979..94edaa16 100644 --- a/src/webhooks/handleDisputeResult.ts +++ b/src/webhooks/handleDisputeResult.ts @@ -2,10 +2,8 @@ import Stripe from 'stripe'; import { UsersService } from '../services/users.service'; import { StorageService } from '../services/storage.service'; import CacheService from '../services/cache.service'; -import { AppConfig } from '../config'; import handleLifetimeRefunded from './handleLifetimeRefunded'; import { PaymentService } from '../services/payment.service'; -import { FastifyBaseLogger } from 'fastify'; import { TiersService } from '../services/tiers.service'; interface HandleDisputeResultProps { @@ -16,8 +14,6 @@ interface HandleDisputeResultProps { storageService: StorageService; cacheService: CacheService; tiersService: TiersService; - log: FastifyBaseLogger; - config: AppConfig; } export async function handleDisputeResult({ @@ -28,37 +24,22 @@ export async function handleDisputeResult({ storageService, cacheService, tiersService, - log, - config, }: HandleDisputeResultProps) { if (dispute.status !== 'lost') { return; } const chargeId = dispute.charge as string; - try { - const charge = await stripe.charges.retrieve(chargeId); - const customerId = typeof charge.customer === 'string' ? charge.customer : (charge.customer?.id as string); - const invoiceId = typeof charge.invoice === 'string' ? charge.invoice : (charge.invoice?.id as string); + const charge = await stripe.charges.retrieve(chargeId); + const customerId = typeof charge.customer === 'string' ? charge.customer : (charge.customer?.id as string); + const invoiceId = typeof charge.invoice === 'string' ? charge.invoice : (charge.invoice?.id as string); - const { subscription: subscriptionId } = await stripe.invoices.retrieve(invoiceId as string); - const { lifetime } = await usersService.findUserByCustomerID(customerId); + const { subscription: subscriptionId } = await stripe.invoices.retrieve(invoiceId); + const { lifetime } = await usersService.findUserByCustomerID(customerId); - if (lifetime) { - await handleLifetimeRefunded( - storageService, - usersService, - charge, - cacheService, - paymentService, - log, - tiersService, - config, - ); - } else { - await paymentService.cancelSubscription(subscriptionId as string); - } - } catch (error) { - throw error; + if (lifetime) { + await handleLifetimeRefunded(storageService, usersService, charge, cacheService, paymentService, tiersService); + } else { + await paymentService.cancelSubscription(subscriptionId as string); } } diff --git a/src/webhooks/handleLifetimeRefunded.ts b/src/webhooks/handleLifetimeRefunded.ts index c54cccef..a4b6b754 100644 --- a/src/webhooks/handleLifetimeRefunded.ts +++ b/src/webhooks/handleLifetimeRefunded.ts @@ -1,13 +1,12 @@ -import { FastifyLoggerInstance } from 'fastify'; import CacheService from '../services/cache.service'; import { StorageService } from '../services/storage.service'; import { UsersService } from '../services/users.service'; -import { AppConfig } from '../config'; import { TierNotFoundError, TiersService } from '../services/tiers.service'; import { handleCancelPlan } from './utils/handleCancelPlan'; import Stripe from 'stripe'; import { PaymentService } from '../services/payment.service'; import { Service } from '../core/users/Tier'; +import Logger from '../Logger'; export default async function handleLifetimeRefunded( storageService: StorageService, @@ -15,9 +14,7 @@ export default async function handleLifetimeRefunded( charge: Stripe.Charge, cacheService: CacheService, paymentsService: PaymentService, - log: FastifyLoggerInstance, tiersService: TiersService, - config: AppConfig, ): Promise { const customerId = charge.customer as string; const userEmail = charge.receipt_email; @@ -35,7 +32,7 @@ export default async function handleLifetimeRefunded( productId = product.id; } - log.info( + Logger.info( `[LIFETIME REFUNDED]: User with customerId ${customerId} found. The uuid of the user is: ${uuid} and productId: ${productId}`, ); @@ -44,7 +41,7 @@ export default async function handleLifetimeRefunded( await cacheService.clearUsedUserPromoCodes(customerId); await cacheService.clearUserTier(uuid); } catch (err) { - log.error(`Error in handleLifetimeRefunded after trying to clear ${customerId} subscription`); + Logger.error(`Error in handleLifetimeRefunded after trying to clear ${customerId} subscription`); } try { @@ -55,11 +52,10 @@ export default async function handleLifetimeRefunded( productId, usersService, tiersService, - log, }); } catch (error) { const err = error as Error; - log.error(`[LIFETIME REFUNDED/ERROR]: Error canceling tier product. ERROR: ${err.stack ?? err.message}`); + Logger.error(`[LIFETIME REFUNDED/ERROR]: Error canceling tier product. ERROR: ${err.stack ?? err.message}`); if (!(error instanceof TierNotFoundError)) { throw error; } diff --git a/src/webhooks/handleSubscriptionCanceled.ts b/src/webhooks/handleSubscriptionCanceled.ts index 56a27986..fe4ecf7f 100644 --- a/src/webhooks/handleSubscriptionCanceled.ts +++ b/src/webhooks/handleSubscriptionCanceled.ts @@ -1,10 +1,8 @@ import { UserType } from './../core/users/User'; -import { FastifyBaseLogger } from 'fastify'; import CacheService from '../services/cache.service'; import { StorageService } from '../services/storage.service'; import { UsersService } from '../services/users.service'; import { PaymentService } from '../services/payment.service'; -import { AppConfig } from '../config'; import Stripe from 'stripe'; import { ObjectStorageService } from '../services/objectStorage.service'; import { handleCancelPlan } from './utils/handleCancelPlan'; @@ -12,6 +10,7 @@ import { TierNotFoundError, TiersService } from '../services/tiers.service'; import { Service } from '../core/users/Tier'; import { stripePaymentsAdapter } from '../infrastructure/adapters/stripe.adapter'; import { Customer } from '../infrastructure/domain/entities/customer'; +import Logger from '../Logger'; function isObjectStorageProduct(meta: Stripe.Metadata): boolean { return !!meta && !!meta.type && meta.type === 'object-storage'; @@ -22,7 +21,6 @@ async function handleObjectStorageSubscriptionCancelled( subscription: Stripe.Subscription, objectStorageService: ObjectStorageService, paymentService: PaymentService, - logger: FastifyBaseLogger, ): Promise { const activeSubscriptions = await paymentService.getActiveSubscriptions(customer.id); const objectStorageActiveSubscriptions = activeSubscriptions.filter( @@ -30,19 +28,19 @@ async function handleObjectStorageSubscriptionCancelled( ); if (objectStorageActiveSubscriptions.length > 0) { - logger.info( + Logger.info( `Preventing removal of an object storage customer ${customer.id} with sub ${subscription.id} due to the existence of another active subscription`, ); return; } - logger.info(`Deleting object storage customer ${customer.id} with sub ${subscription.id}`); + Logger.info(`Deleting object storage customer ${customer.id} with sub ${subscription.id}`); await objectStorageService.deleteAccount({ customerId: customer.id, }); - logger.info(`Object storage customer ${customer.id} with sub ${subscription.id} deleted successfully`); + Logger.info(`Object storage customer ${customer.id} with sub ${subscription.id} deleted successfully`); } export default async function handleSubscriptionCanceled( @@ -53,8 +51,6 @@ export default async function handleSubscriptionCanceled( cacheService: CacheService, objectStorageService: ObjectStorageService, tiersService: TiersService, - log: FastifyBaseLogger, - config: AppConfig, ): Promise { const customerId = subscription.customer as string; const productId = subscription.items.data[0].price.product as string; @@ -62,7 +58,7 @@ export default async function handleSubscriptionCanceled( const customer = await stripePaymentsAdapter.getCustomer(customerId); if (isObjectStorageProduct(productMetadata)) { - await handleObjectStorageSubscriptionCancelled(customer, subscription, objectStorageService, paymentService, log); + await handleObjectStorageSubscriptionCancelled(customer, subscription, objectStorageService, paymentService); return; } @@ -70,7 +66,7 @@ export default async function handleSubscriptionCanceled( const productType = productMetadata?.type === UserType.Business ? UserType.Business : UserType.Individual; - log.info( + Logger.info( `[SUB CANCEL]: User with customerId ${customerId} found. The uuid of the user is: ${uuid} and productId: ${productId}`, ); @@ -78,12 +74,12 @@ export default async function handleSubscriptionCanceled( await cacheService.clearSubscription(customerId, productType); await cacheService.clearUsedUserPromoCodes(customerId); await cacheService.clearUserTier(uuid); - } catch (err) { - log.error(`Error in handleSubscriptionCanceled after trying to clear ${customerId} subscription`); + } catch { + Logger.error(`Error in handleSubscriptionCanceled after trying to clear ${customerId} subscription`); } if (hasBoughtALifetime && productType === UserType.Individual) { - log.info(`User with uuid ${uuid} has a lifetime subscription. No need to downgrade the user.`); + Logger.info(`User with uuid ${uuid} has a lifetime subscription. No need to downgrade the user.`); // This user has switched from a subscription to a lifetime, therefore we do not want to downgrade his space // The space should not be set to Free plan. return; @@ -96,11 +92,10 @@ export default async function handleSubscriptionCanceled( productId, usersService, tiersService, - log, }); } catch (error) { const err = error as Error; - log.error(`[SUB CANCEL/ERROR]: Error canceling tier product. ERROR: ${err.stack ?? err.message}`); + Logger.error(`[SUB CANCEL/ERROR]: Error canceling tier product. ERROR: ${err.stack ?? err.message}`); if (!(error instanceof TierNotFoundError)) { throw error; } diff --git a/src/webhooks/index.ts b/src/webhooks/index.ts index 3452c3fb..983fd57a 100644 --- a/src/webhooks/index.ts +++ b/src/webhooks/index.ts @@ -20,16 +20,25 @@ import { InvoiceCompletedHandler } from './events/invoices/InvoiceCompletedHandl import Logger from '../Logger'; import { stripePaymentsAdapter } from '../infrastructure/adapters/stripe.adapter'; -export default function ( - stripe: Stripe, - storageService: StorageService, - usersService: UsersService, - paymentService: PaymentService, - config: AppConfig, - cacheService: CacheService, - objectStorageService: ObjectStorageService, - tiersService: TiersService, -) { +interface WebhooksParams { + storageService: StorageService; + usersService: UsersService; + paymentService: PaymentService; + config: AppConfig; + cacheService: CacheService; + objectStorageService: ObjectStorageService; + tiersService: TiersService; +} + +export function providerWebhooksEvents({ + storageService, + usersService, + paymentService, + config, + cacheService, + objectStorageService, + tiersService, +}: WebhooksParams) { return async function (fastify: FastifyInstance) { fastify.addContentTypeParser('application/json', { parseAs: 'buffer' }, function (req, body, done) { done(null, body); @@ -40,7 +49,7 @@ export default function ( let event: Stripe.Event; try { - event = stripe.webhooks.constructEvent(req.body, sig, config.STRIPE_WEBHOOK_KEY); + event = stripePaymentsAdapter.getInstance().webhooks.constructEvent(req.body, sig, config.STRIPE_WEBHOOK_KEY); } catch (err) { if (err instanceof Stripe.errors.StripeSignatureVerificationError) { Logger.info('Stripe event could not be verified'); @@ -64,7 +73,13 @@ export default function ( break; case 'payment_intent.amount_capturable_updated': - await handleFundsCaptured(event.data.object, paymentService, objectStorageService, stripe, fastify.log); + await handleFundsCaptured( + event.data.object, + paymentService, + objectStorageService, + stripePaymentsAdapter.getInstance(), + fastify.log, + ); break; case 'customer.subscription.deleted': @@ -76,8 +91,6 @@ export default function ( cacheService, objectStorageService, tiersService, - fastify.log, - config, ); break; @@ -122,7 +135,6 @@ export default function ( const determineLifetimeConditions = new DetermineLifetimeConditions(paymentService, tiersService); const objectStorageWebhookHandler = new ObjectStorageWebhookHandler(objectStorageService, paymentService); const handler = new InvoiceCompletedHandler({ - logger: fastify.log, determineLifetimeConditions, objectStorageWebhookHandler, paymentService, @@ -158,28 +170,25 @@ export default function ( event.data.object, cacheService, paymentService, - fastify.log, tiersService, - config, ); } } break; - case 'charge.dispute.closed': + case 'charge.dispute.closed': { const dispute = event.data.object; await handleDisputeResult({ dispute, - stripe, + stripe: stripePaymentsAdapter.getInstance(), paymentService, usersService, storageService, cacheService, tiersService, - log: fastify.log, - config, }); break; + } default: Logger.info(`No handler registered for event: ${event.type}, id: ${event.id}`); diff --git a/src/webhooks/providers/bit2me/index.ts b/src/webhooks/providers/bit2me/index.ts index 7e405074..9219c8d7 100644 --- a/src/webhooks/providers/bit2me/index.ts +++ b/src/webhooks/providers/bit2me/index.ts @@ -53,7 +53,7 @@ export interface Bit2MePaymentStatusCallback { status: 'new' | 'pending' | 'confirming' | 'paid' | 'expired' | 'paid_after_expired'; } -export default function ({ +export function cryptoProviderWebhooks({ storageService, cacheService, config, @@ -107,7 +107,6 @@ export default function ({ const objectStorageWebhookHandler = new ObjectStorageWebhookHandler(objectStorageService, paymentService); const handler = new InvoiceCompletedHandler({ - logger: fastify.log, determineLifetimeConditions, objectStorageWebhookHandler, paymentService, diff --git a/src/webhooks/utils/handleCancelPlan.ts b/src/webhooks/utils/handleCancelPlan.ts index de637bc3..f2e8d7bc 100644 --- a/src/webhooks/utils/handleCancelPlan.ts +++ b/src/webhooks/utils/handleCancelPlan.ts @@ -2,7 +2,7 @@ import { CustomerId } from '../../types/stripe'; import { UsersService } from '../../services/users.service'; import { TierNotFoundError, TiersService } from '../../services/tiers.service'; import Stripe from 'stripe'; -import { FastifyBaseLogger } from 'fastify'; +import Logger from '../../Logger'; interface HandleCancelPlanProps { customerId: CustomerId; @@ -10,7 +10,6 @@ interface HandleCancelPlanProps { productId: Stripe.Product['id']; usersService: UsersService; tiersService: TiersService; - log: FastifyBaseLogger; isLifetime?: boolean; } @@ -21,22 +20,25 @@ export const handleCancelPlan = async ({ usersService, tiersService, isLifetime, - log, }: HandleCancelPlanProps) => { const user = await usersService.findUserByCustomerID(customerId); const { id: userId } = user; const billingType = isLifetime ? 'lifetime' : 'subscription'; const tier = await tiersService.getTierProductsByProductsId(productId, billingType); - log.info(`[CANCEL PLAN HANDLER]: The user with id ${userId} exists, and the product with id ${tier.id} also exists.`); + Logger.info( + `[CANCEL PLAN HANDLER]: The user with id ${userId} exists, and the product with id ${tier.id} also exists.`, + ); await usersService.updateUser(customerId, { lifetime: false }); - log.info(`[CANCEL PLAN HANDLER]: THe user data for the customer ${userId} has been downgraded in handleCancelPlan`); + Logger.info( + `[CANCEL PLAN HANDLER]: THe user data for the customer ${userId} has been downgraded in handleCancelPlan`, + ); - await tiersService.removeTier({ ...user, email: customerEmail }, productId, log); + await tiersService.removeTier({ ...user, email: customerEmail }, productId); - log.info(`[CANCEL PLAN HANDLER]: The tier for the user ${userId} has been removed`); + Logger.info(`[CANCEL PLAN HANDLER]: The tier for the user ${userId} has been removed`); const userTiers = await tiersService.getTiersProductsByUserId(user.id); @@ -49,7 +51,7 @@ export const handleCancelPlan = async ({ await tiersService.deleteTierFromUser(userId, tierToRemove.id); - log.info( + Logger.info( `[CANCEL PLAN HANDLER]: The user-tier relationship using the user id ${userId} and tier id ${tier.id} has been deleted`, ); }; diff --git a/tests/src/helpers/services-factory.ts b/tests/src/helpers/services-factory.ts index 7c0f0f1b..fc2b45d5 100644 --- a/tests/src/helpers/services-factory.ts +++ b/tests/src/helpers/services-factory.ts @@ -22,7 +22,6 @@ import config from '../../../src/config'; import { DetermineLifetimeConditions } from '../../../src/core/users/DetermineLifetimeConditions'; import { ObjectStorageWebhookHandler } from '../../../src/webhooks/events/ObjectStorageWebhookHandler'; import { InvoiceCompletedHandler } from '../../../src/webhooks/events/invoices/InvoiceCompletedHandler'; -import { getLogger } from '../fixtures'; import { UserFeatureOverridesRepository } from '../../../src/core/users/MongoDBUserFeatureOverridesRepository'; import { UserFeaturesOverridesService } from '../../../src/services/userFeaturesOverride.service'; @@ -103,7 +102,6 @@ export const createTestServices = (overrides: TestServiceOverrides = {}): TestSe const determineLifetimeConditions = new DetermineLifetimeConditions(paymentService, tiersService); const objectStorageWebhookHandler = new ObjectStorageWebhookHandler(objectStorageService, paymentService); const invoiceCompletedHandler = new InvoiceCompletedHandler({ - logger: getLogger(), determineLifetimeConditions, objectStorageWebhookHandler, paymentService, diff --git a/tests/src/services/tiers.service.test.ts b/tests/src/services/tiers.service.test.ts index e554d104..8aa822ee 100644 --- a/tests/src/services/tiers.service.test.ts +++ b/tests/src/services/tiers.service.test.ts @@ -1,5 +1,5 @@ import { TierNotFoundError } from '../../../src/services/tiers.service'; -import { getLogger, getUser, newTier, voidPromise } from '../fixtures'; +import { getUser, newTier, voidPromise } from '../fixtures'; import { Service } from '../../../src/core/users/Tier'; import { UserTier } from '../../../src/core/users/MongoDBUsersTiersRepository'; import { FREE_PLAN_BYTES_SPACE } from '../../../src/constants'; @@ -174,7 +174,7 @@ describe('TiersService tests', () => { .mockImplementation(() => Promise.resolve(null)); await expect( - tiersService.removeTier({ ...mockedUser, email: 'example@internxt.com' }, productId, getLogger()), + tiersService.removeTier({ ...mockedUser, email: 'example@internxt.com' }, productId), ).rejects.toThrow(TierNotFoundError); expect(findTierByProductId).toHaveBeenCalledWith({ productId }); @@ -182,7 +182,6 @@ describe('TiersService tests', () => { it('When removing the tier, then skips the disabled features the tier had', async () => { const mockedUser = getUser(); - const log = getLogger(); const mockedTier = newTier(); const userWithEmail = { ...mockedUser, email: 'example@internxt.com' }; const { productId } = mockedTier; @@ -199,16 +198,15 @@ describe('TiersService tests', () => { .spyOn(tiersService, 'removeVPNFeatures') .mockImplementation(() => Promise.resolve()); - await tiersService.removeTier(userWithEmail, productId, log); + await tiersService.removeTier(userWithEmail, productId); expect(findTierByProductId).toHaveBeenCalledWith({ productId }); - expect(removeDriveFeatures).toHaveBeenCalledWith(userWithEmail.uuid, mockedTier, log); + expect(removeDriveFeatures).toHaveBeenCalledWith(userWithEmail.uuid, mockedTier); expect(removeVPNFeatures).not.toHaveBeenCalled(); }); it('When removing the tier, then removes the applied features', async () => { const mockedUser = getUser(); - const log = getLogger(); const mockedTier = newTier(); const userWithEmail = { ...mockedUser, email: 'example@internxt.com' }; const { productId } = mockedTier; @@ -225,10 +223,10 @@ describe('TiersService tests', () => { .spyOn(tiersService, 'removeVPNFeatures') .mockImplementation(() => Promise.resolve()); - await tiersService.removeTier(userWithEmail, productId, log); + await tiersService.removeTier(userWithEmail, productId); expect(findTierByProductId).toHaveBeenCalledWith({ productId }); - expect(removeDriveFeatures).toHaveBeenCalledWith(userWithEmail.uuid, mockedTier, log); + expect(removeDriveFeatures).toHaveBeenCalledWith(userWithEmail.uuid, mockedTier); expect(removeVPNFeatures).toHaveBeenCalledWith(userWithEmail.uuid, mockedTier.featuresPerService['vpn']); }); }); @@ -243,7 +241,7 @@ describe('TiersService tests', () => { const destroyWorkspace = jest.spyOn(usersService, 'destroyWorkspace').mockImplementation(() => Promise.resolve()); - await tiersService.removeDriveFeatures(uuid, tier, getLogger()); + await tiersService.removeDriveFeatures(uuid, tier); expect(destroyWorkspace).toHaveBeenCalledWith(uuid); }); @@ -268,7 +266,7 @@ describe('TiersService tests', () => { const destroyWorkspaceSpy = jest.spyOn(usersService, 'destroyWorkspace'); const changeStorageSpy = jest.spyOn(storageService, 'updateUserStorageAndTier').mockImplementation(voidPromise); - await tiersService.removeDriveFeatures(uuid, tier, getLogger()); + await tiersService.removeDriveFeatures(uuid, tier); expect(destroyWorkspaceSpy).not.toHaveBeenCalled(); expect(changeStorageSpy).toHaveBeenCalledWith( diff --git a/tests/src/webhooks/events/invoices/InvoiceCompletedHandler.test.ts b/tests/src/webhooks/events/invoices/InvoiceCompletedHandler.test.ts index 6b6b959d..aff525ef 100644 --- a/tests/src/webhooks/events/invoices/InvoiceCompletedHandler.test.ts +++ b/tests/src/webhooks/events/invoices/InvoiceCompletedHandler.test.ts @@ -433,7 +433,6 @@ describe('Testing the handler when an invoice is completed', () => { Customer.toDomain(mockedCustomer), totalQuantity, mockedLifetimeTier, - expect.anything(), lifetimeMockedMaxSpaceBytes, ); expect(applyVpnFeaturesSpy).toHaveBeenCalledWith( @@ -483,7 +482,6 @@ describe('Testing the handler when an invoice is completed', () => { Customer.toDomain(mockedCustomer), totalQuantity, mockedTier, - expect.anything(), undefined, ); expect(applyVpnFeaturesSpy).toHaveBeenCalledWith( @@ -530,7 +528,6 @@ describe('Testing the handler when an invoice is completed', () => { Customer.toDomain(mockedCustomer), totalQuantity, mockedTier, - expect.anything(), undefined, ); expect(applyVpnFeaturesSpy).toHaveBeenCalledWith( diff --git a/tests/src/webhooks/handleDisputeResult.test.ts b/tests/src/webhooks/handleDisputeResult.test.ts index 47a47caf..0d082bd7 100644 --- a/tests/src/webhooks/handleDisputeResult.test.ts +++ b/tests/src/webhooks/handleDisputeResult.test.ts @@ -1,8 +1,7 @@ import axios from 'axios'; -import config from '../../../src/config'; import { handleDisputeResult } from '../../../src/webhooks/handleDisputeResult'; import handleLifetimeRefunded from '../../../src/webhooks/handleLifetimeRefunded'; -import { getCharge, getDispute, getInvoice, getLogger, getUser, voidPromise } from '../fixtures'; +import { getCharge, getDispute, getInvoice, getUser, voidPromise } from '../fixtures'; import { createTestServices } from '../helpers/services-factory'; jest.mock('../../../src/webhooks/handleLifetimeRefunded', () => ({ @@ -23,7 +22,6 @@ const { stripe, paymentService, usersRepository, cacheService, usersService, sto createTestServices({ stripe: mockStripe, }); -const logger = getLogger(); describe('handleDisputeResult()', () => { beforeEach(() => { @@ -49,12 +47,10 @@ describe('handleDisputeResult()', () => { await handleDisputeResult({ dispute: mockedDispute, cacheService: cacheService, - config, paymentService, usersService, stripe, storageService, - log: logger, tiersService, }); @@ -89,12 +85,10 @@ describe('handleDisputeResult()', () => { await handleDisputeResult({ dispute: mockedDispute, cacheService, - config, paymentService, usersService, stripe, storageService, - log: logger, tiersService, }); @@ -107,9 +101,7 @@ describe('handleDisputeResult()', () => { mockedCharge, cacheService, paymentService, - logger, tiersService, - config, ); }); }); @@ -140,12 +132,10 @@ describe('handleDisputeResult()', () => { await handleDisputeResult({ dispute: mockedDispute, cacheService, - config, paymentService, usersService, stripe, storageService, - log: logger, tiersService, }); diff --git a/tests/src/webhooks/handleLifetimeRefunded.test.ts b/tests/src/webhooks/handleLifetimeRefunded.test.ts index 30e5bf24..e1a2dc63 100644 --- a/tests/src/webhooks/handleLifetimeRefunded.test.ts +++ b/tests/src/webhooks/handleLifetimeRefunded.test.ts @@ -1,7 +1,6 @@ import Stripe from 'stripe'; import { TierNotFoundError } from '../../../src/services/tiers.service'; -import { getCharge, getInvoice, getLogger, getUser, newTier } from '../fixtures'; -import config from '../../../src/config'; +import { getCharge, getInvoice, getUser, newTier } from '../fixtures'; import { handleCancelPlan } from '../../../src/webhooks/utils/handleCancelPlan'; import handleLifetimeRefunded from '../../../src/webhooks/handleLifetimeRefunded'; import { FREE_PLAN_BYTES_SPACE } from '../../../src/constants'; @@ -9,7 +8,6 @@ import { createTestServices } from '../helpers/services-factory'; jest.mock('../../../src/webhooks/utils/handleCancelPlan'); -const logger = getLogger(); const { paymentService, usersService, storageService, tiersService, cacheService } = createTestServices(); beforeEach(() => { @@ -37,9 +35,7 @@ describe('Process when a lifetime is refunded', () => { mockedCharge, cacheService, paymentService, - logger, tiersService, - config, ); expect(findUserByCustomerIdSpy).toHaveBeenCalledWith(mockedCharge.customer); @@ -51,7 +47,6 @@ describe('Process when a lifetime is refunded', () => { isLifetime: mockedUser.lifetime, usersService: usersService, tiersService: tiersService, - log: logger, }); }); @@ -84,9 +79,7 @@ describe('Process when a lifetime is refunded', () => { mockedCharge, cacheService, paymentService, - logger, tiersService, - config, ); expect(findUserByCustomerIdSpy).toHaveBeenCalledWith(mockedCharge.customer); @@ -111,16 +104,7 @@ describe('Process when a lifetime is refunded', () => { (handleCancelPlan as jest.Mock).mockRejectedValue(randomError); await expect( - handleLifetimeRefunded( - storageService, - usersService, - mockedCharge, - cacheService, - paymentService, - logger, - tiersService, - config, - ), + handleLifetimeRefunded(storageService, usersService, mockedCharge, cacheService, paymentService, tiersService), ).rejects.toThrow(randomError); }); }); diff --git a/tests/src/webhooks/handleSubscriptionCanceled.test.ts b/tests/src/webhooks/handleSubscriptionCanceled.test.ts index 0cc16688..407933f2 100644 --- a/tests/src/webhooks/handleSubscriptionCanceled.test.ts +++ b/tests/src/webhooks/handleSubscriptionCanceled.test.ts @@ -1,7 +1,6 @@ import { TierNotFoundError } from '../../../src/services/tiers.service'; import { FastifyBaseLogger } from 'fastify'; import { getCreatedSubscription, getCustomer, getLogger, getProduct, getUser, newTier } from '../fixtures'; -import config from '../../../src/config'; import handleSubscriptionCanceled from '../../../src/webhooks/handleSubscriptionCanceled'; import { handleCancelPlan } from '../../../src/webhooks/utils/handleCancelPlan'; import { FREE_PLAN_BYTES_SPACE } from '../../../src/constants'; @@ -41,8 +40,6 @@ describe('Process when a subscription is cancelled', () => { cacheService, objectStorageService, tiersService, - logger, - config, ); expect(getProductSpy).toHaveBeenCalledWith(mockedSubscription.items.data[0].price.product); @@ -54,7 +51,6 @@ describe('Process when a subscription is cancelled', () => { productId: mockedSubscription.items.data[0].price.product, usersService, tiersService, - log: logger, }); }); @@ -90,8 +86,6 @@ describe('Process when a subscription is cancelled', () => { cacheService, objectStorageService, tiersService, - logger, - config, ); expect(getProductSpy).toHaveBeenCalledWith(mockedSubscription.items.data[0].price.product); @@ -126,8 +120,6 @@ describe('Process when a subscription is cancelled', () => { cacheService, objectStorageService, tiersService, - logger, - config, ), ).rejects.toThrow(randomError); }); diff --git a/tests/src/webhooks/utils/handleCancelPlan.test.ts b/tests/src/webhooks/utils/handleCancelPlan.test.ts index 642dbefe..9f2b7194 100644 --- a/tests/src/webhooks/utils/handleCancelPlan.test.ts +++ b/tests/src/webhooks/utils/handleCancelPlan.test.ts @@ -1,5 +1,5 @@ import { TierNotFoundError } from '../../../../src/services/tiers.service'; -import { getCustomer, getLogger, getUser, newTier, voidPromise } from '../../fixtures'; +import { getCustomer, getUser, newTier, voidPromise } from '../../fixtures'; import { handleCancelPlan } from '../../../../src/webhooks/utils/handleCancelPlan'; import { createTestServices } from '../../helpers/services-factory'; @@ -13,7 +13,7 @@ beforeEach(() => { describe('Handling canceled plans and refunded lifetimes', () => { it('When the tier id to remove the user-tier relationship does not exists, then an error indicating so is thrown', async () => { const mockedCustomer = getCustomer(); - const log = getLogger(); + const mockedUser = getUser({ customerId: mockedCustomer.id, lifetime: false }); const mockedTier = newTier(); const mockedRandomTier = newTier({ @@ -34,7 +34,6 @@ describe('Handling canceled plans and refunded lifetimes', () => { productId: mockedRandomTier.productId, tiersService, usersService, - log, }), ).rejects.toThrow(TierNotFoundError); @@ -42,7 +41,6 @@ describe('Handling canceled plans and refunded lifetimes', () => { expect(removeTierSpy).toHaveBeenCalledWith( { ...mockedUser, email: mockedCustomer.email as string }, mockedRandomTier.productId, - log, ); expect(userTiersSpy).toHaveBeenCalledWith(mockedUser.id); expect(deleteTierFromUserSpy).not.toHaveBeenCalled(); @@ -50,7 +48,7 @@ describe('Handling canceled plans and refunded lifetimes', () => { it('When the user cancels a subscription, then the tier is removed and the free space is applied', async () => { const mockedCustomer = getCustomer(); - const log = getLogger(); + const mockedUser = getUser({ customerId: mockedCustomer.id, lifetime: false }); const mockedTier = newTier(); @@ -67,14 +65,12 @@ describe('Handling canceled plans and refunded lifetimes', () => { productId: mockedTier.productId, tiersService, usersService, - log, }); expect(updateUserSpy).toHaveBeenCalledWith(mockedCustomer.id, { lifetime: false }); expect(removeTierSpy).toHaveBeenCalledWith( { ...mockedUser, email: mockedCustomer.email as string }, mockedTier.productId, - log, ); expect(userTiersSpy).toHaveBeenCalledWith(mockedUser.id); expect(deleteTierFromUserSpy).toHaveBeenCalledWith(mockedUser.id, mockedTier.id); @@ -82,7 +78,7 @@ describe('Handling canceled plans and refunded lifetimes', () => { it('When the user cancels a lifetime (refund), then the lifetime field is set to false, the tier is removed and the free space is applied', async () => { const mockedCustomer = getCustomer(); - const log = getLogger(); + const mockedUser = getUser({ customerId: mockedCustomer.id, lifetime: true }); const mockedTier = newTier({ billingType: 'lifetime' }); @@ -104,7 +100,6 @@ describe('Handling canceled plans and refunded lifetimes', () => { productId: mockedTier.productId, tiersService, usersService, - log, }); expect(updateUserSpy).toHaveBeenCalledWith(mockedCustomer.id, { lifetime: false }); @@ -112,7 +107,6 @@ describe('Handling canceled plans and refunded lifetimes', () => { expect(removeTierSpy).toHaveBeenCalledWith( { ...mockedUser, email: mockedCustomer.email as string }, mockedTier.productId, - log, ); expect(userTiersSpy).toHaveBeenCalledWith(mockedUser.id); expect(deleteTierFromUserSpy).toHaveBeenCalledWith(mockedUser.id, mockedTier.id);