diff --git a/src/__tests__/controllers/UserController.test.ts b/src/__tests__/controllers/UserController.test.ts index f609712..6ef6b2a 100644 --- a/src/__tests__/controllers/UserController.test.ts +++ b/src/__tests__/controllers/UserController.test.ts @@ -78,4 +78,24 @@ describe('UserController.secondOnboarding', () => { expect(res.json).toHaveBeenCalledWith({}); expect(userService.getSecondOnboardings).not.toHaveBeenCalled(); }); + + it('does not 500 when app_version is missing from the request (regression: semver gte on undefined)', async () => { + // gte(undefined, minVersion) used to throw "Invalid version" before any + // onboarding logic ran. first_seen = now keeps us in the <7-day early return. + const res = makeRes(); + await expect( + controller.secondOnboarding( + { + body: { + rc_id: 'rc_123', + region: 'USA', + first_seen: Math.floor(Date.now() / 1000), + }, + } as any, + res, + ), + ).resolves.toBeDefined(); + + expect(res.json).toHaveBeenCalledWith({}); + }); }); diff --git a/src/controllers/UserController.ts b/src/controllers/UserController.ts index 419118f..2d609bb 100644 --- a/src/controllers/UserController.ts +++ b/src/controllers/UserController.ts @@ -4,7 +4,7 @@ import cookie from 'cookie'; import { UserEventEnum } from '../types/user'; import moment from 'moment-timezone'; import { SubscriptionService } from '../services/SubscriptionService'; -import { gte } from 'semver'; +import { gte, valid } from 'semver'; export class UserController { constructor( @@ -14,6 +14,14 @@ export class UserController { private readonly minVersion = '5.6.0'; + /// semver's gte throws when app_version is missing/malformed (e.g. an older + /// client that omits it from the body), which surfaced as an unlogged 500 on + /// /user/second_onboarding. Treat any non-semver value as "not supported". + private meetsMinVersion(version?: string): boolean { + const parsed = valid(version); + return parsed != null && gte(parsed, this.minVersion); + } + public async getAuth(req: IRequest, res: IResponse): Promise { const user = req.user; res.json({ user, message: !user ? 'login' : 'dashboard' }); @@ -206,7 +214,7 @@ export class UserController { return res.json({}); } - const isVersionSupported = gte(app_version, this.minVersion); + const isVersionSupported = this.meetsMinVersion(app_version); /// Only allow AUS, ESP, PHL, MEX, RUS region for tip only onboarding if ( @@ -307,7 +315,7 @@ export class UserController { external_id: rc_id, }); - const isVersionSupported = gte(app_version, this.minVersion); + const isVersionSupported = this.meetsMinVersion(app_version); switch (region) { case 'USA': if (totalCount <= 1) {