@metaadri/secureauth 1.1.0 → 1.2.1
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/bin/cli.js +14 -4
- package/package.json +1 -1
- package/src/index.js +8 -8
- package/src/questions.js +18 -7
- package/src/scaffolder.js +1 -0
- package/templates/database/db.sqlite.js +7 -2
- package/templates/routes/authRoutes.js +0 -1
- package/templates/server.js +11 -12
package/bin/cli.js
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
const { init } = require('../src/index');
|
|
4
4
|
|
|
5
|
-
const
|
|
5
|
+
const args = process.argv.slice(2);
|
|
6
|
+
const command = args[0];
|
|
7
|
+
const defaults = args.includes('--defaults') || args.includes('--yes');
|
|
6
8
|
|
|
7
9
|
switch (command) {
|
|
8
10
|
case 'init':
|
|
9
|
-
init();
|
|
11
|
+
init(defaults);
|
|
10
12
|
break;
|
|
11
13
|
case '--help':
|
|
12
14
|
case '-h':
|
|
@@ -15,8 +17,16 @@ switch (command) {
|
|
|
15
17
|
SecureAuth CLI - Enterprise authentication for Express apps
|
|
16
18
|
|
|
17
19
|
Usage:
|
|
18
|
-
npx secureauth init
|
|
19
|
-
npx secureauth --
|
|
20
|
+
npx secureauth init Add SecureAuth to your project (interactive)
|
|
21
|
+
npx secureauth init --defaults Add SecureAuth with all default options (non-interactive)
|
|
22
|
+
npx secureauth init --yes Same as --defaults
|
|
23
|
+
npx secureauth --help Show this help message
|
|
24
|
+
|
|
25
|
+
Environment variables (with --defaults):
|
|
26
|
+
SECUREAUTH_DB=sqlite|postgres
|
|
27
|
+
SECUREAUTH_PORT=3000
|
|
28
|
+
SECUREAUTH_JWT_SECRET=<your-secret>
|
|
29
|
+
SECUREAUTH_FEATURES=ddos,admin,accountLockout
|
|
20
30
|
`);
|
|
21
31
|
break;
|
|
22
32
|
}
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -76,7 +76,7 @@ ${logger.separator('Next Steps')}
|
|
|
76
76
|
`);
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
async function init() {
|
|
79
|
+
async function init(defaults) {
|
|
80
80
|
logger.banner();
|
|
81
81
|
|
|
82
82
|
const targetDir = process.cwd();
|
|
@@ -87,22 +87,22 @@ async function init() {
|
|
|
87
87
|
|
|
88
88
|
const projectType = report.hasPackageJson
|
|
89
89
|
? 'existing'
|
|
90
|
-
: await askProjectType();
|
|
90
|
+
: await askProjectType(defaults);
|
|
91
91
|
|
|
92
92
|
const answers = { projectName: report.projectName };
|
|
93
93
|
|
|
94
94
|
if (projectType === 'new') {
|
|
95
|
-
answers.projectName = await askProjectName();
|
|
95
|
+
answers.projectName = await askProjectName(defaults);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
answers.database = await askDatabase();
|
|
99
|
-
answers.port = await askPort(3000);
|
|
100
|
-
answers.jwtSecret = await askJwtSecret();
|
|
98
|
+
answers.database = await askDatabase(defaults);
|
|
99
|
+
answers.port = await askPort(3000, defaults);
|
|
100
|
+
answers.jwtSecret = await askJwtSecret(defaults);
|
|
101
101
|
logger.info(logger.dim('Not sure which features to pick? Visit https://secureauth106293.netlify.app/ for guidance.'));
|
|
102
|
-
answers.features = await askFeatures();
|
|
102
|
+
answers.features = await askFeatures(defaults);
|
|
103
103
|
|
|
104
104
|
logger.info('');
|
|
105
|
-
const confirmed = await askConfirm();
|
|
105
|
+
const confirmed = await askConfirm(defaults);
|
|
106
106
|
if (!confirmed) {
|
|
107
107
|
logger.warn('Installation cancelled.');
|
|
108
108
|
return;
|
package/src/questions.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const { prompt } = require('enquirer');
|
|
2
2
|
|
|
3
|
-
async function askProjectType() {
|
|
3
|
+
async function askProjectType(defaults) {
|
|
4
|
+
if (defaults) return 'existing';
|
|
4
5
|
const { type } = await prompt({
|
|
5
6
|
type: 'select',
|
|
6
7
|
name: 'type',
|
|
@@ -13,7 +14,8 @@ async function askProjectType() {
|
|
|
13
14
|
return type;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
async function askProjectName() {
|
|
17
|
+
async function askProjectName(defaults) {
|
|
18
|
+
if (defaults) return 'my-secure-app';
|
|
17
19
|
const { name } = await prompt({
|
|
18
20
|
type: 'input',
|
|
19
21
|
name: 'name',
|
|
@@ -25,7 +27,8 @@ async function askProjectName() {
|
|
|
25
27
|
return name;
|
|
26
28
|
}
|
|
27
29
|
|
|
28
|
-
async function askDatabase() {
|
|
30
|
+
async function askDatabase(defaults) {
|
|
31
|
+
if (defaults) return process.env.SECUREAUTH_DB || 'sqlite';
|
|
29
32
|
const { db } = await prompt({
|
|
30
33
|
type: 'select',
|
|
31
34
|
name: 'db',
|
|
@@ -39,7 +42,8 @@ async function askDatabase() {
|
|
|
39
42
|
return db;
|
|
40
43
|
}
|
|
41
44
|
|
|
42
|
-
async function askPort(defaultPort) {
|
|
45
|
+
async function askPort(defaultPort, defaults) {
|
|
46
|
+
if (defaults) return parseInt(process.env.SECUREAUTH_PORT || String(defaultPort), 10);
|
|
43
47
|
const { port } = await prompt({
|
|
44
48
|
type: 'input',
|
|
45
49
|
name: 'port',
|
|
@@ -51,8 +55,9 @@ async function askPort(defaultPort) {
|
|
|
51
55
|
return parseInt(port, 10);
|
|
52
56
|
}
|
|
53
57
|
|
|
54
|
-
async function askJwtSecret() {
|
|
58
|
+
async function askJwtSecret(defaults) {
|
|
55
59
|
const autoSecret = require('crypto').randomBytes(32).toString('hex');
|
|
60
|
+
if (defaults) return process.env.SECUREAUTH_JWT_SECRET || autoSecret;
|
|
56
61
|
const { choice } = await prompt({
|
|
57
62
|
type: 'select',
|
|
58
63
|
name: 'choice',
|
|
@@ -73,7 +78,12 @@ async function askJwtSecret() {
|
|
|
73
78
|
return secret;
|
|
74
79
|
}
|
|
75
80
|
|
|
76
|
-
async function askFeatures() {
|
|
81
|
+
async function askFeatures(defaults) {
|
|
82
|
+
if (defaults) {
|
|
83
|
+
const env = process.env.SECUREAUTH_FEATURES;
|
|
84
|
+
if (env) return env.split(',').map(s => s.trim());
|
|
85
|
+
return ['ddos', 'accountLockout'];
|
|
86
|
+
}
|
|
77
87
|
const { features } = await prompt({
|
|
78
88
|
type: 'multiselect',
|
|
79
89
|
name: 'features',
|
|
@@ -88,7 +98,8 @@ async function askFeatures() {
|
|
|
88
98
|
return features;
|
|
89
99
|
}
|
|
90
100
|
|
|
91
|
-
async function askConfirm() {
|
|
101
|
+
async function askConfirm(defaults) {
|
|
102
|
+
if (defaults) return true;
|
|
92
103
|
const { confirmed } = await prompt({
|
|
93
104
|
type: 'toggle',
|
|
94
105
|
name: 'confirmed',
|
package/src/scaffolder.js
CHANGED
|
@@ -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();
|