@metaadri/secureauth 1.2.0 → 1.2.2
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
CHANGED
package/src/scaffolder.js
CHANGED
|
@@ -30,6 +30,7 @@ const LOCKOUT_CHECK_CODE = `
|
|
|
30
30
|
|
|
31
31
|
const LOCKOUT_INCREMENT_CODE = `
|
|
32
32
|
const failedAttempts = await userModel.incrementFailedAttempts(user.id);
|
|
33
|
+
const remaining = MAX_FAILED_ATTEMPTS - failedAttempts;
|
|
33
34
|
`;
|
|
34
35
|
|
|
35
36
|
const LOCKOUT_TRIGGER_CODE = `
|
|
@@ -116,9 +117,61 @@ function scaffold(targetDir, answers) {
|
|
|
116
117
|
fileCount++;
|
|
117
118
|
}
|
|
118
119
|
|
|
120
|
+
postProcess(targetDir);
|
|
119
121
|
return fileCount;
|
|
120
122
|
}
|
|
121
123
|
|
|
124
|
+
function postProcess(targetDir) {
|
|
125
|
+
const files = {
|
|
126
|
+
'controllers/authController.js': [
|
|
127
|
+
{
|
|
128
|
+
search: /(const failedAttempts = await userModel\.incrementFailedAttempts\(user\.id\);)(?!\s+const remaining)/,
|
|
129
|
+
replace: '$1\n const remaining = MAX_FAILED_ATTEMPTS - failedAttempts;'
|
|
130
|
+
}
|
|
131
|
+
],
|
|
132
|
+
'server.js': [
|
|
133
|
+
{
|
|
134
|
+
search: /require\('dotenv'\)\.config\(\);/,
|
|
135
|
+
replace: "const path = require('path');\nrequire('dotenv').config({ path: path.join(__dirname, '.env') });"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
search: /initDatabase\(\)\s*\.then\(async\s*\(\)\s*=>\s*\{[\s\S]*?await seedAdminUser\(\);[\s\S]*?await seedDemoUser\(\);[\s\S]*?dbReady\s*=\s*true;[\s\S]*?console\.log\('Database initialized and seeded'\);\s*\}\)[\s\S]*?\.catch\(err\s*=>\s*\{[\s\S]*?console\.error\('Database initialization failed:',\s*err\.message\);\s*\}\);/,
|
|
139
|
+
replace: "try {\n initDatabase();\n seedAdminUser();\n seedDemoUser();\n dbReady = true;\n console.log('Database initialized and seeded');\n} catch (err) {\n console.error('Database initialization failed:', err.message);\n}"
|
|
140
|
+
}
|
|
141
|
+
],
|
|
142
|
+
'database/db.sqlite.js': [
|
|
143
|
+
{
|
|
144
|
+
search: /query:\s*\(text,\s*params\)\s*=>\s*\{[^}]*const stmt\s*=\s*db\.prepare\(text\);[^}]*const rows\s*=\s*params\s*\?\s*stmt\.all\(\.\.\.params\)\s*:\s*stmt\.all\(\);[^}]*return\s*\{\s*rows\s*\};[^}]*\}/,
|
|
145
|
+
replace: "query: (text, params) => {\n const stmt = db.prepare(text);\n const sql = text.trim().toUpperCase();\n if (sql.startsWith('SELECT')) {\n const rows = params ? stmt.all(...params) : stmt.all();\n return { rows };\n }\n const info = params ? stmt.run(...params) : stmt.run();\n return { rows: [], changes: info.changes };\n }"
|
|
146
|
+
}
|
|
147
|
+
],
|
|
148
|
+
'routes/authRoutes.js': [
|
|
149
|
+
{
|
|
150
|
+
search: /router\.post\('\/demo\/login', authController\.demoLogin\);\s*/,
|
|
151
|
+
replace: ''
|
|
152
|
+
}
|
|
153
|
+
]
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
for (const [relative, rules] of Object.entries(files)) {
|
|
157
|
+
const filePath = path.join(targetDir, relative);
|
|
158
|
+
if (!fs.existsSync(filePath)) continue;
|
|
159
|
+
try {
|
|
160
|
+
let content = fs.readFileSync(filePath, 'utf-8');
|
|
161
|
+
const before = content;
|
|
162
|
+
for (const rule of rules) {
|
|
163
|
+
content = content.replace(rule.search, rule.replace);
|
|
164
|
+
}
|
|
165
|
+
if (content !== before) {
|
|
166
|
+
fs.writeFileSync(filePath, content, 'utf-8');
|
|
167
|
+
logger.info(`Patched ${relative}`);
|
|
168
|
+
}
|
|
169
|
+
} catch {
|
|
170
|
+
// skip unreadable files
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
122
175
|
function collectFiles(dir) {
|
|
123
176
|
const results = [];
|
|
124
177
|
for (const entry of fs.readdirSync(dir)) {
|
|
@@ -111,8 +111,13 @@ module.exports = {
|
|
|
111
111
|
db: {
|
|
112
112
|
query: (text, params) => {
|
|
113
113
|
const stmt = db.prepare(text);
|
|
114
|
-
const
|
|
115
|
-
|
|
114
|
+
const sql = text.trim().toUpperCase();
|
|
115
|
+
if (sql.startsWith('SELECT')) {
|
|
116
|
+
const rows = params ? stmt.all(...params) : stmt.all();
|
|
117
|
+
return { rows };
|
|
118
|
+
}
|
|
119
|
+
const info = params ? stmt.run(...params) : stmt.run();
|
|
120
|
+
return { rows: [], changes: info.changes };
|
|
116
121
|
}
|
|
117
122
|
}
|
|
118
123
|
};
|
|
@@ -8,7 +8,6 @@ const loginLimiter = createRateLimiter(5, 15);
|
|
|
8
8
|
|
|
9
9
|
router.post('/register', authController.register);
|
|
10
10
|
router.post('/login', loginLimiter, authController.loginStep1);
|
|
11
|
-
router.post('/demo/login', authController.demoLogin);
|
|
12
11
|
router.post('/verify-2fa', loginLimiter, authController.verifyTOTP);
|
|
13
12
|
router.get('/dashboard', checkAndRefreshToken, authController.getDashboard);
|
|
14
13
|
router.get('/login-history', checkAndRefreshToken, authController.getLoginHistory);
|
package/templates/server.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
require('
|
|
1
|
+
const path = require('path');
|
|
2
|
+
require('dotenv').config({ path: path.join(__dirname, '.env') });
|
|
2
3
|
const express = require('express');
|
|
3
4
|
const cors = require('cors');
|
|
4
|
-
const path = require('path');
|
|
5
5
|
const helmet = require('helmet');
|
|
6
6
|
|
|
7
7
|
const authRoutes = require('./routes/authRoutes');
|
|
@@ -62,16 +62,15 @@ app.get('/', (req, res) => {
|
|
|
62
62
|
|
|
63
63
|
let dbReady = false;
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
.
|
|
73
|
-
|
|
74
|
-
});
|
|
65
|
+
try {
|
|
66
|
+
initDatabase();
|
|
67
|
+
seedAdminUser();
|
|
68
|
+
seedDemoUser();
|
|
69
|
+
dbReady = true;
|
|
70
|
+
console.log('Database initialized and seeded');
|
|
71
|
+
} catch (err) {
|
|
72
|
+
console.error('Database initialization failed:', err.message);
|
|
73
|
+
}
|
|
75
74
|
|
|
76
75
|
app.use((req, res, next) => {
|
|
77
76
|
if (dbReady) return next();
|