diff --git a/services/web/app/src/Features/Subscription/SubscriptionController.js b/services/web/app/src/Features/Subscription/SubscriptionController.js index 74594076c8..0050ca9487 100644 --- a/services/web/app/src/Features/Subscription/SubscriptionController.js +++ b/services/web/app/src/Features/Subscription/SubscriptionController.js @@ -355,16 +355,16 @@ async function successfulSubscription(req, res) { } } +const pauseSubscriptionSchema = z.object({ + params: z.object({ + pauseCycles: z.coerce.number().int().max(12), + }), +}) + async function pauseSubscription(req, res, next) { const user = SessionManager.getSessionUser(req.session) - const pauseCycles = req.params.pauseCycles - if (!('pauseCycles' in req.params)) { - return HttpErrorHandler.badRequest( - req, - res, - `Pausing subscription requires a 'pauseCycles' argument with number of billing cycles to pause for` - ) - } + const { params } = validateReq(req, pauseSubscriptionSchema) + const pauseCycles = params.pauseCycles if (pauseCycles < 0) { return HttpErrorHandler.badRequest( req, diff --git a/services/web/app/src/Features/Subscription/SubscriptionRouter.mjs b/services/web/app/src/Features/Subscription/SubscriptionRouter.mjs index 29ca931c06..232c7ab1ab 100644 --- a/services/web/app/src/Features/Subscription/SubscriptionRouter.mjs +++ b/services/web/app/src/Features/Subscription/SubscriptionRouter.mjs @@ -6,7 +6,6 @@ import TeamInvitesController from './TeamInvitesController.mjs' import { RateLimiter } from '../../infrastructure/RateLimiter.js' import RateLimiterMiddleware from '../Security/RateLimiterMiddleware.js' import Settings from '@overleaf/settings' -import { Joi, validate } from '../../infrastructure/Validation.js' const teamInviteRateLimiter = new RateLimiter('team-invite', { points: 10, @@ -201,11 +200,6 @@ export default { webRouter.post( '/user/subscription/pause/:pauseCycles', AuthenticationController.requireLogin(), - validate({ - params: Joi.object({ - pauseCycles: Joi.number().integer().max(12), - }), - }), RateLimiterMiddleware.rateLimit(subscriptionRateLimiter), SubscriptionController.pauseSubscription ) diff --git a/services/web/test/unit/src/Subscription/SubscriptionControllerTests.js b/services/web/test/unit/src/Subscription/SubscriptionControllerTests.js index 130f583b04..881d0ef0c5 100644 --- a/services/web/test/unit/src/Subscription/SubscriptionControllerTests.js +++ b/services/web/test/unit/src/Subscription/SubscriptionControllerTests.js @@ -10,6 +10,7 @@ const SubscriptionHelper = require('../../../../app/src/Features/Subscription/Su const { AI_ADD_ON_CODE, } = require('../../../../app/src/Features/Subscription/AiHelper') +const Errors = require('../../../../app/src/Features/Errors/Errors') const mockSubscriptions = { 'subscription-123-active': { @@ -481,18 +482,19 @@ describe('SubscriptionController', function () { this.res = new MockResponse() this.req = new MockRequest() this.next = sinon.stub() - await this.SubscriptionController.pauseSubscription( - this.req, - this.res, - this.next - ) - expect(this.res.statusCode).to.equal(400) + await expect( + this.SubscriptionController.pauseSubscription( + this.req, + this.res, + this.next + ) + ).to.be.rejectedWith(Errors.NotFoundError) }) it('should throw an error if an invalid pause length is provided', async function () { this.res = new MockResponse() this.req = new MockRequest() - this.req.params = { pauseCycles: -10 } + this.req.params = { pauseCycles: '-10' } this.next = sinon.stub() await this.SubscriptionController.pauseSubscription( this.req, @@ -505,7 +507,7 @@ describe('SubscriptionController', function () { it('should return a 200 when requesting a pause', async function () { this.res = new MockResponse() this.req = new MockRequest() - this.req.params = { pauseCycles: 3 } + this.req.params = { pauseCycles: '3' } this.next = sinon.stub() await this.SubscriptionController.pauseSubscription( this.req,