From 2b2a1bc6ce108c32905fcae0a74db128bac9b419 Mon Sep 17 00:00:00 2001 From: Aaditya Jaiswal Date: Tue, 31 Mar 2026 19:31:33 +0530 Subject: [PATCH] three issues fixed just backing up --- src/config/sso.ts | 3 ++- src/controllers/form16.controller.ts | 33 ++++++++++++++++++++++------ src/routes/form16.routes.ts | 4 ++-- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/config/sso.ts b/src/config/sso.ts index b67dbf1..8874e76 100644 --- a/src/config/sso.ts +++ b/src/config/sso.ts @@ -4,7 +4,8 @@ import { SSOConfig, SSOUserData } from '../types/auth.types'; // This ensures values are read after secrets are loaded from Google Secret Manager const ssoConfig: SSOConfig = { get jwtSecret() { return process.env.JWT_SECRET || ''; }, - get jwtExpiry() { return process.env.JWT_EXPIRY || '24h'; }, + // VAPT: reduce access token lifetime to 30 minutes by default + get jwtExpiry() { return process.env.JWT_EXPIRY || '30m'; }, get refreshTokenExpiry() { return process.env.REFRESH_TOKEN_EXPIRY || '7d'; }, get sessionSecret() { return process.env.SESSION_SECRET || ''; }, // Use only FRONTEND_URL from environment - no fallbacks diff --git a/src/controllers/form16.controller.ts b/src/controllers/form16.controller.ts index 79203ff..6426388 100644 --- a/src/controllers/form16.controller.ts +++ b/src/controllers/form16.controller.ts @@ -23,6 +23,26 @@ import { Dealer } from '@models/Dealer'; */ export class Form16Controller { + // Minimal PII masking for 26AS APIs – mask PAN in all responses + private maskPan(pan: unknown): string | undefined { + if (pan == null) return undefined; + const s = String(pan).trim(); + if (!s) return undefined; + const last4 = s.slice(-4); + if (s.length <= 4) return 'XXXX'; + return `XXXXXXX${last4}`; + } + + private mask26asEntry(entry: any): any { + if (!entry) return entry; + const plain = typeof entry.toJSON === 'function' ? entry.toJSON() : entry; + const masked = { ...plain }; + if (masked.panNumber) { + masked.panNumber = this.maskPan(masked.panNumber); + } + return masked; + } + private toSapCsv(sap: { trnsUniqNo?: string | null; tdsTransId?: string | null; @@ -257,11 +277,8 @@ export class Form16Controller { limit, offset, }); - return ResponseHandler.success( - res, - { entries: result.rows, total: result.total, summary: result.summary }, - '26AS entries fetched' - ); + const entries = (result.rows || []).map((row: any) => this.mask26asEntry(row)); + return ResponseHandler.success(res, { entries, total: result.total, summary: result.summary }, '26AS entries fetched'); } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; logger.error('[Form16Controller] list26as error:', error); @@ -300,7 +317,8 @@ export class Form16Controller { statusOltas: (body.statusOltas as string) || undefined, remarks: (body.remarks as string) || undefined, }); - return ResponseHandler.success(res, { entry }, '26AS entry created'); + const masked = this.mask26asEntry(entry); + return ResponseHandler.success(res, { entry: masked }, '26AS entry created'); } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; logger.error('[Form16Controller] create26as error:', error); @@ -339,7 +357,8 @@ export class Form16Controller { if (!entry) { return ResponseHandler.error(res, '26AS entry not found', 404); } - return ResponseHandler.success(res, { entry }, '26AS entry updated'); + const masked = this.mask26asEntry(entry); + return ResponseHandler.success(res, { entry: masked }, '26AS entry updated'); } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; logger.error('[Form16Controller] update26as error:', error); diff --git a/src/routes/form16.routes.ts b/src/routes/form16.routes.ts index 4f4a374..c986f9c 100644 --- a/src/routes/form16.routes.ts +++ b/src/routes/form16.routes.ts @@ -45,10 +45,10 @@ const upload = multer({ limits: { fileSize: 15 * 1024 * 1024 }, }); -// 26AS upload: .txt only, 5MB, memory storage (parse then bulk insert) +// 26AS upload: .txt only, 40MB, memory storage (parse then bulk insert) const upload26asTxt = multer({ storage: multer.memoryStorage(), - limits: { fileSize: 5 * 1024 * 1024 }, + limits: { fileSize: 40 * 1024 * 1024 }, fileFilter: (_req, file, cb) => { const ext = path.extname(file.originalname || '').toLowerCase(); const isTxt = ext === '.txt' || (file.mimetype && (file.mimetype === 'text/plain' || file.mimetype === 'application/octet-stream'));