mbkauthe 3.2.0 โ†’ 3.3.0

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/README.md CHANGED
@@ -119,24 +119,44 @@ app.get('/admin', validateSession, checkRolePermission(['SuperAdmin']), (req, re
119
119
  app.listen(3000);
120
120
  ```
121
121
 
122
- ## ๐Ÿงช Testing
123
122
 
124
- MBKAuthe includes comprehensive test coverage for all authentication features:
123
+ ## ๐Ÿงช Testing & Git Hooks
124
+
125
+ MBKAuthe includes comprehensive test coverage for all authentication features. **A pre-commit hook is provided to ensure code quality:**
126
+
127
+ ### Pre-commit Hook (Automatic Test Runner)
128
+
129
+ - Located at `scripts/pre-commit` and `scripts/pre-commit` (Node.js, cross-platform)
130
+ - Starts the dev server, runs all tests, and blocks commits if any test fails
131
+ - The dev server is automatically stopped after tests complete
132
+ - Ensures you never commit code that breaks tests
133
+
134
+ ### Git Hook Setup
135
+
136
+ Hooks are auto-configured every time you run `npm run dev`, `npm test`, or `npm run test:watch` (see `scripts/setup-hooks.js`).
137
+
138
+ If you ever need to manually set up hooks:
139
+
140
+ ```bash
141
+ node scripts/setup-hooks.js
142
+ ```
143
+
144
+ ### Running Tests
125
145
 
126
146
  ```bash
127
- # Run all tests
147
+ # Run all tests (auto-configures hooks)
128
148
  npm test
129
149
 
130
- # Run tests in watch mode (auto-rerun on changes)
150
+ # Run tests in watch mode (auto-configures hooks)
131
151
  npm run test:watch
132
152
 
133
- # Run with development flags
153
+ # Run with development flags (auto-configures hooks)
134
154
  npm run dev
135
155
  ```
136
156
 
137
157
  **Test Coverage:**
138
158
  - โœ… Authentication flows (login, 2FA, logout)
139
- - โœ… OAuth integration (GitHub)
159
+ - โœ… OAuth integration (GitHub)
140
160
  - โœ… Session management and security
141
161
  - โœ… Role-based access control
142
162
  - โœ… API endpoints and error handling
package/docs/api.md CHANGED
@@ -764,9 +764,7 @@ app.get('/protected', validateSession, (req, res) => {
764
764
  req.session.user = {
765
765
  id: 1, // User ID
766
766
  username: "john.doe", // Username
767
- UserName: "john.doe", // Username (alias)
768
767
  role: "NormalUser", // User role
769
- Role: "NormalUser", // User role (alias)
770
768
  sessionId: "abc123...", // 64-char hex session ID
771
769
  }
772
770
  ```
package/docs/db.md CHANGED
@@ -43,7 +43,7 @@ CREATE TABLE user_github (
43
43
  user_name VARCHAR(50) REFERENCES "Users"("UserName"),
44
44
  github_id VARCHAR(255) UNIQUE,
45
45
  github_username VARCHAR(255),
46
- access_token VARCHAR(255),
46
+ access_token TEXT,
47
47
  created_at TimeStamp WITH TIME ZONE DEFAULT NOW(),
48
48
  updated_at TimeStamp WITH TIME ZONE DEFAULT NOW()
49
49
  );
@@ -58,7 +58,7 @@ CREATE TABLE user_google (
58
58
  user_name VARCHAR(50) REFERENCES "Users"("UserName"),
59
59
  google_id VARCHAR(255) UNIQUE,
60
60
  google_email VARCHAR(255),
61
- access_token VARCHAR(255),
61
+ access_token TEXT,
62
62
  created_at TimeStamp WITH TIME ZONE DEFAULT NOW(),
63
63
  updated_at TimeStamp WITH TIME ZONE DEFAULT NOW()
64
64
  );
package/index.d.ts CHANGED
@@ -11,9 +11,7 @@ declare global {
11
11
  interface Request {
12
12
  user?: {
13
13
  username: string;
14
- UserName: string;
15
14
  role: 'SuperAdmin' | 'NormalUser' | 'Guest';
16
- Role: 'SuperAdmin' | 'NormalUser' | 'Guest';
17
15
  };
18
16
  userRole?: 'SuperAdmin' | 'NormalUser' | 'Guest';
19
17
  }
@@ -22,20 +20,17 @@ declare global {
22
20
  user?: {
23
21
  id: number;
24
22
  username: string;
25
- UserName: string;
26
23
  role: 'SuperAdmin' | 'NormalUser' | 'Guest';
27
- Role: 'SuperAdmin' | 'NormalUser' | 'Guest';
28
24
  sessionId: string;
29
25
  allowedApps?: string[];
30
26
  };
31
27
  preAuthUser?: {
32
28
  id: number;
33
29
  username: string;
34
- UserName?: string;
35
30
  role: 'SuperAdmin' | 'NormalUser' | 'Guest';
36
- Role?: 'SuperAdmin' | 'NormalUser' | 'Guest';
37
31
  loginMethod?: 'password' | 'github' | 'google';
38
32
  redirectUrl?: string | null;
33
+ allowedApps?: string[];
39
34
  };
40
35
  oauthRedirect?: string;
41
36
  oauthCsrfToken?: string;
@@ -80,9 +75,7 @@ declare module 'mbkauthe' {
80
75
  export interface SessionUser {
81
76
  id: number;
82
77
  username: string;
83
- UserName: string;
84
78
  role: UserRole;
85
- Role: UserRole;
86
79
  sessionId: string;
87
80
  allowedApps?: string[];
88
81
  }
@@ -90,9 +83,8 @@ declare module 'mbkauthe' {
90
83
  export interface PreAuthUser {
91
84
  id: number;
92
85
  username: string;
93
- UserName?: string;
94
86
  role: UserRole;
95
- Role?: UserRole;
87
+ allowedApps?: string[];
96
88
  loginMethod?: 'password' | 'github' | 'google';
97
89
  redirectUrl?: string | null;
98
90
  }
@@ -81,9 +81,7 @@ export async function sessionRestorationMiddleware(req, res, next) {
81
81
  req.session.user = {
82
82
  id: user.id,
83
83
  username: user.UserName,
84
- UserName: user.UserName,
85
84
  role: user.Role,
86
- Role: user.Role,
87
85
  sessionId: normalizedSessionId,
88
86
  allowedApps: user.AllowedApps,
89
87
  };
@@ -103,7 +103,6 @@ export async function checkTrustedDevice(req, username) {
103
103
  id: deviceUser.id,
104
104
  username: username,
105
105
  role: deviceUser.Role,
106
- Role: deviceUser.Role,
107
106
  allowedApps: deviceUser.AllowedApps,
108
107
  };
109
108
  }
@@ -166,9 +165,7 @@ export async function completeLoginProcess(req, res, user, redirectUrl = null, t
166
165
  req.session.user = {
167
166
  id: user.id,
168
167
  username: username,
169
- UserName: username,
170
168
  role: user.role || user.Role,
171
- Role: user.role || user.Role,
172
169
  sessionId,
173
170
  allowedApps: user.allowedApps || user.AllowedApps,
174
171
  };
@@ -346,7 +343,6 @@ router.post("/api/login", LoginLimit, async (req, res) => {
346
343
  id: user.id,
347
344
  username: user.UserName,
348
345
  role: user.Role,
349
- Role: user.Role,
350
346
  allowedApps: user.AllowedApps,
351
347
  };
352
348
  const requestedRedirect = typeof redirect === 'string' && redirect.startsWith('/') && !redirect.startsWith('//') ? redirect : null;
@@ -360,7 +356,7 @@ router.post("/api/login", LoginLimit, async (req, res) => {
360
356
  id: user.id,
361
357
  username: user.UserName,
362
358
  role: user.Role,
363
- Role: user.Role,
359
+ allowedApps: user.AllowedApps,
364
360
  redirectUrl: requestedRedirect
365
361
  };
366
362
  console.log(`[mbkauthe] 2FA required for user: ${trimmedUsername}`);
@@ -372,7 +368,6 @@ router.post("/api/login", LoginLimit, async (req, res) => {
372
368
  id: user.id,
373
369
  username: user.UserName,
374
370
  role: user.Role,
375
- Role: user.Role,
376
371
  allowedApps: user.AllowedApps,
377
372
  };
378
373
  const requestedRedirect = typeof redirect === 'string' && redirect.startsWith('/') && !redirect.startsWith('//') ? redirect : null;
@@ -443,7 +438,10 @@ router.post("/api/verify-2fa", TwoFALimit, csrfProtection, async (req, res) => {
443
438
  const shouldTrustDevice = trustDevice === true || trustDevice === 'true';
444
439
 
445
440
  try {
446
- const query = `SELECT tfa."TwoFASecret", u."AllowedApps" FROM "TwoFA" tfa JOIN "Users" u ON tfa."UserName" = u."UserName" WHERE tfa."UserName" = $1`;
441
+ // Use cached allowedApps from preAuthUser to avoid extra database join
442
+ const cachedAllowedApps = req.session.preAuthUser?.allowedApps;
443
+
444
+ const query = `SELECT tfa."TwoFASecret" FROM "TwoFA" tfa WHERE tfa."UserName" = $1`;
447
445
  const twoFAResult = await dblogin.query({ name: 'verify-2fa-secret', text: query, values: [username] });
448
446
 
449
447
  if (twoFAResult.rows.length === 0 || !twoFAResult.rows[0].TwoFASecret) {
@@ -453,7 +451,7 @@ router.post("/api/verify-2fa", TwoFALimit, csrfProtection, async (req, res) => {
453
451
  }
454
452
 
455
453
  const sharedSecret = twoFAResult.rows[0].TwoFASecret;
456
- const allowedApps = twoFAResult.rows[0].AllowedApps;
454
+ const allowedApps = cachedAllowedApps;
457
455
  const tokenValidates = speakeasy.totp.verify({
458
456
  secret: sharedSecret,
459
457
  encoding: "base32",
@@ -355,9 +355,8 @@ const createOAuthCallback = (provider, strategy) => {
355
355
  req.session.preAuthUser = {
356
356
  id: user.id,
357
357
  username: user.UserName,
358
- UserName: user.UserName,
359
358
  role: user.Role,
360
- Role: user.Role,
359
+ allowedApps: user.AllowedApps,
361
360
  loginMethod: provider.toLowerCase(),
362
361
  redirectUrl: oauthRedirect || null
363
362
  };
@@ -387,9 +386,7 @@ const handleOAuthRedirect = async (req, res, user, type) => {
387
386
  const userForSession = {
388
387
  id: user.id,
389
388
  username: user.UserName,
390
- UserName: user.UserName,
391
389
  role: user.Role,
392
- Role: user.Role,
393
390
  allowedApps: user.AllowedApps,
394
391
  };
395
392
 
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "mbkauthe",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "description": "MBKTech's reusable authentication system for Node.js applications.",
5
5
  "main": "index.js",
6
6
  "type": "module",
7
7
  "types": "index.d.ts",
8
8
  "scripts": {
9
- "dev": "cross-env test=dev nodemon index.js",
10
- "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
11
- "test:watch": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watch"
9
+ "dev": "node scripts/setup-hooks.js && cross-env test=dev nodemon index.js",
10
+ "test": "node scripts/setup-hooks.js && node --experimental-vm-modules node_modules/jest/bin/jest.js",
11
+ "test:watch": "node scripts/setup-hooks.js && node --experimental-vm-modules node_modules/jest/bin/jest.js --watch"
12
12
  },
13
13
  "repository": {
14
14
  "type": "git",