@metaadri/secureauth 1.2.3 → 1.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/patcher.js +50 -32
package/package.json
CHANGED
package/src/patcher.js
CHANGED
|
@@ -188,14 +188,12 @@ function generateMigrationSql(dbType) {
|
|
|
188
188
|
if (dbType === 'postgres') {
|
|
189
189
|
return `-- SecureAuth: Add account lockout columns
|
|
190
190
|
ALTER TABLE users ADD COLUMN IF NOT EXISTS failed_login_attempts INTEGER DEFAULT 0;
|
|
191
|
-
ALTER TABLE users ADD COLUMN IF NOT EXISTS locked_until
|
|
192
|
-
ALTER TABLE users ADD COLUMN IF NOT EXISTS last_failed_login TEXT;
|
|
191
|
+
ALTER TABLE users ADD COLUMN IF NOT EXISTS locked_until TIMESTAMPTZ;
|
|
193
192
|
`;
|
|
194
193
|
}
|
|
195
194
|
return `-- SecureAuth: Add account lockout columns
|
|
196
|
-
ALTER TABLE users ADD COLUMN failed_login_attempts INTEGER DEFAULT 0;
|
|
197
|
-
ALTER TABLE users ADD COLUMN locked_until TEXT;
|
|
198
|
-
ALTER TABLE users ADD COLUMN last_failed_login TEXT;
|
|
195
|
+
ALTER TABLE users ADD COLUMN IF NOT EXISTS failed_login_attempts INTEGER DEFAULT 0;
|
|
196
|
+
ALTER TABLE users ADD COLUMN IF NOT EXISTS locked_until TEXT;
|
|
199
197
|
`;
|
|
200
198
|
}
|
|
201
199
|
|
|
@@ -218,7 +216,7 @@ function addEnvVars(content) {
|
|
|
218
216
|
}
|
|
219
217
|
|
|
220
218
|
function addHelper(content) {
|
|
221
|
-
const loginRouteRegex = /(?:router|app)\s*\.\s*(?:post|get)\s*\(\s*['"](?:\/api\/)?(?:login|signin)['"]/;
|
|
219
|
+
const loginRouteRegex = /(?:router|app)\s*\.\s*(?:post|get)\s*\(\s*['"](?:\/(?:api\/)?)?(?:login|signin)['"]/;
|
|
222
220
|
const loginMatch = content.match(loginRouteRegex);
|
|
223
221
|
if (!loginMatch) return { content, modified: false };
|
|
224
222
|
|
|
@@ -253,27 +251,37 @@ function addIncrementReset(content, dbVar, paramStyle) {
|
|
|
253
251
|
const incrementBlock = generateIncrementBlock(dbVar, paramStyle);
|
|
254
252
|
|
|
255
253
|
const afterBrace = content.slice(blockStart + 1);
|
|
256
|
-
const
|
|
257
|
-
|
|
254
|
+
const errorResponsePatterns = [
|
|
255
|
+
/\breturn\s+res\.status\(40[13]\)/,
|
|
256
|
+
/\bres\.status\(40[13]\)/,
|
|
257
|
+
];
|
|
258
|
+
let firstError = -1;
|
|
259
|
+
for (const p of errorResponsePatterns) {
|
|
260
|
+
const m = afterBrace.search(p);
|
|
261
|
+
if (m !== -1 && (firstError === -1 || m < firstError)) {
|
|
262
|
+
firstError = m;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (firstError === -1) return { content, modified: false };
|
|
258
266
|
|
|
259
|
-
const insertPos = blockStart + 1 +
|
|
267
|
+
const insertPos = blockStart + 1 + firstError;
|
|
260
268
|
content = content.slice(0, insertPos) + incrementBlock + content.slice(insertPos);
|
|
261
269
|
|
|
262
270
|
const closingBraceIndex = findMatchingBrace(content, blockStart);
|
|
263
271
|
if (closingBraceIndex === -1) return { content, modified: false };
|
|
264
272
|
|
|
265
273
|
const afterInvalidBlock = content.slice(closingBraceIndex + 1);
|
|
266
|
-
const
|
|
267
|
-
if (
|
|
268
|
-
const secondBlockStart = afterInvalidBlock.indexOf('{',
|
|
274
|
+
const secondInvalidMatch = afterInvalidBlock.match(/if\s*\(\s*!is(?:Valid|PasswordValid)\s*\)/);
|
|
275
|
+
if (secondInvalidMatch) {
|
|
276
|
+
const secondBlockStart = afterInvalidBlock.indexOf('{', secondInvalidMatch.index);
|
|
269
277
|
if (secondBlockStart !== -1) {
|
|
270
278
|
const secondClosing = findMatchingBrace(afterInvalidBlock, secondBlockStart);
|
|
271
279
|
if (secondClosing !== -1) {
|
|
272
280
|
const afterSecond = afterInvalidBlock.slice(secondClosing + 1);
|
|
273
281
|
const resetBlock = generateResetBlock(dbVar, paramStyle);
|
|
274
|
-
const
|
|
275
|
-
if (
|
|
276
|
-
const insertAfterSecond = closingBraceIndex + 1 + secondClosing + 1 +
|
|
282
|
+
const successPos = findSuccessResponse(afterSecond);
|
|
283
|
+
if (successPos !== -1) {
|
|
284
|
+
const insertAfterSecond = closingBraceIndex + 1 + secondClosing + 1 + successPos;
|
|
277
285
|
content = content.slice(0, insertAfterSecond) + resetBlock + content.slice(insertAfterSecond);
|
|
278
286
|
return { content, modified: true };
|
|
279
287
|
}
|
|
@@ -281,23 +289,39 @@ function addIncrementReset(content, dbVar, paramStyle) {
|
|
|
281
289
|
}
|
|
282
290
|
}
|
|
283
291
|
|
|
284
|
-
const
|
|
285
|
-
const
|
|
286
|
-
if (
|
|
292
|
+
const afterBlock = content.slice(closingBraceIndex + 1);
|
|
293
|
+
const hasAnotherCompare = afterBlock.match(/await\s+bcrypt\.compare\(/);
|
|
294
|
+
if (hasAnotherCompare) {
|
|
287
295
|
return { content, modified: false };
|
|
288
296
|
}
|
|
289
297
|
|
|
290
298
|
const resetBlock = generateResetBlock(dbVar, paramStyle);
|
|
291
|
-
const
|
|
292
|
-
if (
|
|
293
|
-
const
|
|
294
|
-
content = content.slice(0,
|
|
299
|
+
const successPos = findSuccessResponse(afterBlock);
|
|
300
|
+
if (successPos !== -1) {
|
|
301
|
+
const insertPosReset = closingBraceIndex + 1 + successPos;
|
|
302
|
+
content = content.slice(0, insertPosReset) + resetBlock + content.slice(insertPosReset);
|
|
295
303
|
return { content, modified: true };
|
|
296
304
|
}
|
|
297
305
|
|
|
298
306
|
return { content, modified: false };
|
|
299
307
|
}
|
|
300
308
|
|
|
309
|
+
function findSuccessResponse(str) {
|
|
310
|
+
const patterns = [
|
|
311
|
+
/\breturn\s+res\.status\(2\d{2}\)\s*\.\s*json\(/,
|
|
312
|
+
/\breturn\s+res\.json\(/,
|
|
313
|
+
/\bres\.status\(2\d{2}\)\s*\.\s*json\(/,
|
|
314
|
+
/\bres\.json\(/
|
|
315
|
+
];
|
|
316
|
+
for (const p of patterns) {
|
|
317
|
+
const m = str.match(p);
|
|
318
|
+
if (m) {
|
|
319
|
+
return m.index;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return -1;
|
|
323
|
+
}
|
|
324
|
+
|
|
301
325
|
function addStatus423Return(content, dbVar, paramStyle) {
|
|
302
326
|
const lockedResponse = `\n return res.status(423).json({
|
|
303
327
|
error: 'Account locked',
|
|
@@ -334,23 +358,17 @@ function findMatchingBrace(str, openPos) {
|
|
|
334
358
|
}
|
|
335
359
|
|
|
336
360
|
function writeMigration(targetDir, dbType) {
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
fs.mkdirSync(migrationsDir, { recursive: true });
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
const timestamp = new Date().toISOString().replace(/[^0-9]/g, '').slice(0, 14);
|
|
343
|
-
const fileName = `${timestamp}_add_account_lockout.sql`;
|
|
344
|
-
const filePath = path.join(migrationsDir, fileName);
|
|
361
|
+
const fileName = 'migration_lockout.sql';
|
|
362
|
+
const filePath = path.join(targetDir, fileName);
|
|
345
363
|
|
|
346
364
|
if (fs.existsSync(filePath)) {
|
|
347
|
-
logger.warn(
|
|
365
|
+
logger.warn(`${fileName} already exists — skipping`);
|
|
348
366
|
return null;
|
|
349
367
|
}
|
|
350
368
|
|
|
351
369
|
const sql = generateMigrationSql(dbType);
|
|
352
370
|
fs.writeFileSync(filePath, sql, 'utf-8');
|
|
353
|
-
logger.success(`Created
|
|
371
|
+
logger.success(`Created ${fileName}`);
|
|
354
372
|
return filePath;
|
|
355
373
|
}
|
|
356
374
|
|