mbkauthe 4.7.2 → 4.8.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
@@ -22,7 +22,7 @@
22
22
  - PostgreSQL session management
23
23
  - Multi-session support (configurable concurrent sessions per user)
24
24
  - Optional TOTP-based 2FA with trusted devices
25
- - OAuth login (GitHub & Google)
25
+ - Social login (GitHub App & Google OAuth)
26
26
  - Role-based access: SuperAdmin, NormalUser, Guest
27
27
  - CSRF protection & rate limiting
28
28
  - Easy Express.js integration
@@ -101,9 +101,9 @@ These are only mounted when `process.env.env === "dev"`:
101
101
 
102
102
  Enable via `MBKAUTH_TWO_FA_ENABLE=true`. Trusted devices can skip 2FA for a set duration.
103
103
 
104
- ## 🔄 OAuth Integration
104
+ ## 🔄 Social Login Integration
105
105
 
106
- **GitHub / Google OAuth:** Configure apps and credentials via `.env` or `mbkautheVar`. Users must link accounts before login.
106
+ **GitHub App / Google OAuth:** Configure credentials via `.env` or `mbkautheVar`. Users must link accounts before login.
107
107
 
108
108
  ## 🎨 Customization
109
109
 
package/docs/api.md CHANGED
@@ -179,7 +179,7 @@ Renders the main login page.
179
179
  **Response:** HTML page with login form
180
180
 
181
181
  **Template Variables:**
182
- - `githubLoginEnabled` - Whether GitHub OAuth is enabled
182
+ - `githubLoginEnabled` - Whether GitHub App login is enabled
183
183
  - `googleLoginEnabled` - Whether Google OAuth is enabled
184
184
  - `customURL` - Redirect URL after login
185
185
  - `userLoggedIn` - Whether user is already authenticated
@@ -317,8 +317,8 @@ The endpoints below are active in the router but are not fully expanded above. U
317
317
 
318
318
  **OAuth:**
319
319
 
320
- - `GET /mbkauthe/api/github/login` - Starts GitHub OAuth login flow.
321
- - `GET /mbkauthe/api/github/login/callback` - GitHub OAuth callback.
320
+ - `GET /mbkauthe/api/github/login` - Starts GitHub App login flow.
321
+ - `GET /mbkauthe/api/github/login/callback` - GitHub App callback.
322
322
  - `GET /mbkauthe/api/google/login` - Starts Google OAuth login flow.
323
323
  - `GET /mbkauthe/api/google/login/callback` - Google OAuth callback.
324
324
 
@@ -1222,11 +1222,11 @@ GET /mbkauthe/test
1222
1222
 
1223
1223
  ### OAuth Endpoints
1224
1224
 
1225
- #### GitHub OAuth
1225
+ #### GitHub App
1226
1226
 
1227
1227
  ##### `GET /mbkauthe/api/github/login`
1228
1228
 
1229
- Initiates the GitHub OAuth authentication flow.
1229
+ Initiates the GitHub App authentication flow.
1230
1230
 
1231
1231
  **Rate Limit:** 10 requests per 5 minutes
1232
1232
 
@@ -1235,11 +1235,11 @@ Initiates the GitHub OAuth authentication flow.
1235
1235
  **Query Parameters:**
1236
1236
  - `redirect` (optional) - Relative URL to redirect after successful authentication (must start with `/` to prevent open redirect attacks)
1237
1237
 
1238
- **Response:** Redirects to GitHub OAuth authorization page
1238
+ **Response:** Redirects to GitHub authorization page
1239
1239
 
1240
1240
  **Prerequisites:**
1241
1241
  - `GITHUB_LOGIN_ENABLED=true` in environment
1242
- - Valid `GITHUB_CLIENT_ID` and `GITHUB_CLIENT_SECRET` configured
1242
+ - Valid `GITHUB_APP_CLIENT_ID` and `GITHUB_APP_CLIENT_SECRET` configured
1243
1243
  - User's GitHub account must be linked to an MBKAuth account in `user_github` table
1244
1244
 
1245
1245
  **Example:**
@@ -1250,9 +1250,9 @@ GET /mbkauthe/api/github/login?redirect=/dashboard
1250
1250
  **Workflow:**
1251
1251
  1. User clicks "Login with GitHub"
1252
1252
  2. CSRF token generated and stored in session
1253
- 3. Redirects to GitHub for authorization
1254
- 4. GitHub redirects back to callback URL
1255
- 5. System verifies GitHub account is linked
1253
+ 3. Redirects to GitHub authorization page
1254
+ 4. GitHub redirects back to callback URL with authorization `code`
1255
+ 5. System verifies `github_id` is linked
1256
1256
  6. If 2FA enabled, prompts for 2FA
1257
1257
  7. Creates session and redirects to specified URL
1258
1258
 
@@ -1260,7 +1260,7 @@ GET /mbkauthe/api/github/login?redirect=/dashboard
1260
1260
 
1261
1261
  ##### `GET /mbkauthe/api/github/login/callback`
1262
1262
 
1263
- Handles the OAuth callback from GitHub after user authorization.
1263
+ Handles the callback from GitHub after user authorization.
1264
1264
 
1265
1265
  **Rate Limit:** Inherited from OAuth rate limiter (10 requests per 5 minutes)
1266
1266
 
@@ -1277,7 +1277,7 @@ Handles the OAuth callback from GitHub after user authorization.
1277
1277
  - **GitHub Not Linked**: Returns error if GitHub account is not in `user_github` table
1278
1278
  - **Account Inactive**: Returns error if user account is deactivated
1279
1279
  - **Not Authorized**: Returns error if user is not allowed to access the application
1280
- - **GitHub Auth Error**: Returns error for any OAuth-related failures
1280
+ - **GitHub Auth Error**: Returns error for provider authentication failures
1281
1281
 
1282
1282
  **Success Flow:**
1283
1283
  ```
package/docs/db.md CHANGED
@@ -85,7 +85,9 @@ CREATE TABLE IF NOT EXISTS user_github (
85
85
  user_name VARCHAR(50) REFERENCES "Users"("UserName"),
86
86
  github_id VARCHAR(255) UNIQUE,
87
87
  github_username VARCHAR(255),
88
- access_token TEXT,
88
+ installation_id BIGINT,
89
+ installation_target_type VARCHAR(32),
90
+ access_token VARCHAR(255),
89
91
  created_at TimeStamp WITH TIME ZONE DEFAULT NOW(),
90
92
  updated_at TimeStamp WITH TIME ZONE DEFAULT NOW()
91
93
  );
package/docs/db.sql CHANGED
@@ -49,11 +49,17 @@ CREATE TABLE IF NOT EXISTS user_github (
49
49
  user_name VARCHAR(50) REFERENCES "Users"("UserName"),
50
50
  github_id VARCHAR(255) UNIQUE,
51
51
  github_username VARCHAR(255),
52
+ installation_id BIGINT,
53
+ installation_target_type VARCHAR(32),
52
54
  access_token TEXT,
53
55
  created_at TimeStamp WITH TIME ZONE DEFAULT NOW(),
54
56
  updated_at TimeStamp WITH TIME ZONE DEFAULT NOW()
55
57
  );
56
58
 
59
+ ALTER TABLE user_github
60
+ ADD COLUMN IF NOT EXISTS installation_id BIGINT,
61
+ ADD COLUMN IF NOT EXISTS installation_target_type VARCHAR(32);
62
+
57
63
  -- Add indexes for performance optimization
58
64
  CREATE INDEX IF NOT EXISTS idx_user_github_github_id ON user_github (github_id);
59
65
  CREATE INDEX IF NOT EXISTS idx_user_github_user_name ON user_github (user_name);
package/docs/env.md CHANGED
@@ -95,14 +95,26 @@ This document describes the environment variables MBKAuth expects and keeps brie
95
95
  - Required: No
96
96
 
97
97
  - GITHUB_LOGIN_ENABLED / GOOGLE_LOGIN_ENABLED
98
- - Description: Enable OAuth providers.
98
+ - Description: Enable social login providers.
99
99
  - Default: `false`
100
- - If `true`, corresponding `*_CLIENT_ID` and `*_CLIENT_SECRET` are required.
100
+ - If `GOOGLE_LOGIN_ENABLED=true`, `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET` are required.
101
+ - If `GITHUB_LOGIN_ENABLED=true`, GitHub App client credentials are required.
101
102
 
102
- - GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET / GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET
103
- - Description: OAuth credentials (put in `mbkautheVar` preferred, or `mbkauthShared`).
104
- - Required when provider enabled.
105
- - Create Github OAuth App: https://github.com/settings/developers
103
+ - GITHUB_APP_SLUG
104
+ - Description: GitHub App slug (optional for login flow in this package; useful for install/link flows handled elsewhere).
105
+ - Required: No
106
+ - Create GitHub App: https://github.com/settings/apps
107
+
108
+ - GITHUB_APP_CLIENT_ID / GITHUB_APP_CLIENT_SECRET
109
+ - Description: GitHub App OAuth credentials used for user sign-in.
110
+ - Required when `GITHUB_LOGIN_ENABLED=true`.
111
+
112
+ - GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET
113
+ - Description: Legacy fallback keys if app-prefixed keys are not provided.
114
+
115
+ - GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET
116
+ - Description: Google OAuth credentials.
117
+ - Required when `GOOGLE_LOGIN_ENABLED=true`.
106
118
  - Create Google OAuth: https://console.cloud.google.com/
107
119
 
108
120
  ---
package/index.d.ts CHANGED
@@ -55,8 +55,9 @@ declare module 'mbkauthe' {
55
55
  COOKIE_EXPIRE_TIME?: number;
56
56
  DEVICE_TRUST_DURATION_DAYS?: number;
57
57
  GITHUB_LOGIN_ENABLED?: 'true' | 'false' | 'f';
58
- GITHUB_CLIENT_ID?: string;
59
- GITHUB_CLIENT_SECRET?: string;
58
+ GITHUB_APP_SLUG?: string;
59
+ GITHUB_APP_CLIENT_ID?: string;
60
+ GITHUB_APP_CLIENT_SECRET?: string;
60
61
  GOOGLE_LOGIN_ENABLED?: 'true' | 'false' | 'f';
61
62
  GOOGLE_CLIENT_ID?: string;
62
63
  GOOGLE_CLIENT_SECRET?: string;
@@ -66,8 +67,9 @@ declare module 'mbkauthe' {
66
67
 
67
68
  export interface OAuthConfig {
68
69
  GITHUB_LOGIN_ENABLED?: 'true' | 'false' | 'f';
69
- GITHUB_CLIENT_ID?: string;
70
- GITHUB_CLIENT_SECRET?: string;
70
+ GITHUB_APP_SLUG?: string;
71
+ GITHUB_APP_CLIENT_ID?: string;
72
+ GITHUB_APP_CLIENT_SECRET?: string;
71
73
  GOOGLE_LOGIN_ENABLED?: 'true' | 'false' | 'f';
72
74
  GOOGLE_CLIENT_ID?: string;
73
75
  GOOGLE_CLIENT_SECRET?: string;
@@ -132,6 +134,8 @@ declare module 'mbkauthe' {
132
134
  user_name: string;
133
135
  github_id: string;
134
136
  github_username: string;
137
+ installation_id?: number;
138
+ installation_target_type?: string;
135
139
  access_token: string;
136
140
  created_at: Date;
137
141
  updated_at: Date;
@@ -64,7 +64,7 @@ function validateConfiguration() {
64
64
  const keysToCheck = [
65
65
  "APP_NAME", "DEVICE_TRUST_DURATION_DAYS", "EncPass", "Main_SECRET_TOKEN", "SESSION_SECRET_KEY",
66
66
  "IS_DEPLOYED", "LOGIN_DB", "MBKAUTH_TWO_FA_ENABLE", "COOKIE_EXPIRE_TIME", "DOMAIN", "loginRedirectURL",
67
- "GITHUB_LOGIN_ENABLED", "GITHUB_CLIENT_ID", "GITHUB_CLIENT_SECRET", "GOOGLE_LOGIN_ENABLED", "GOOGLE_CLIENT_ID",
67
+ "GITHUB_LOGIN_ENABLED", "GITHUB_APP_SLUG", "GITHUB_APP_CLIENT_ID", "GITHUB_APP_CLIENT_SECRET", "GITHUB_CLIENT_ID", "GITHUB_CLIENT_SECRET", "GOOGLE_LOGIN_ENABLED", "GOOGLE_CLIENT_ID",
68
68
  "GOOGLE_CLIENT_SECRET", "MAX_SESSIONS_PER_USER"
69
69
  ];
70
70
 
@@ -145,11 +145,14 @@ function validateConfiguration() {
145
145
 
146
146
  // Validate GitHub login configuration
147
147
  if (mbkautheVar.GITHUB_LOGIN_ENABLED === "true") {
148
- if (!mbkautheVar.GITHUB_CLIENT_ID || mbkautheVar.GITHUB_CLIENT_ID.trim() === '') {
149
- errors.push("mbkautheVar.GITHUB_CLIENT_ID is required when GITHUB_LOGIN_ENABLED is 'true'");
148
+ const hasGithubClientId = !!(mbkautheVar.GITHUB_APP_CLIENT_ID || mbkautheVar.GITHUB_CLIENT_ID);
149
+ const hasGithubClientSecret = !!(mbkautheVar.GITHUB_APP_CLIENT_SECRET || mbkautheVar.GITHUB_CLIENT_SECRET);
150
+
151
+ if (!hasGithubClientId) {
152
+ errors.push("mbkautheVar.GITHUB_APP_CLIENT_ID (or GITHUB_CLIENT_ID) is required when GITHUB_LOGIN_ENABLED is 'true'");
150
153
  }
151
- if (!mbkautheVar.GITHUB_CLIENT_SECRET || mbkautheVar.GITHUB_CLIENT_SECRET.trim() === '') {
152
- errors.push("mbkautheVar.GITHUB_CLIENT_SECRET is required when GITHUB_LOGIN_ENABLED is 'true'");
154
+ if (!hasGithubClientSecret) {
155
+ errors.push("mbkautheVar.GITHUB_APP_CLIENT_SECRET (or GITHUB_CLIENT_SECRET) is required when GITHUB_LOGIN_ENABLED is 'true'");
153
156
  }
154
157
  }
155
158
 
@@ -6,6 +6,32 @@ import { ErrorCodes, createErrorResponse } from "../utils/errors.js";
6
6
  import { hashApiToken } from "#config.js";
7
7
  import { canAccessMethod } from "#config.js";
8
8
 
9
+ /**
10
+ * Decide if the incoming request should return JSON errors instead of HTML.
11
+ * Non-browser clients (API calls / AJAX) should get JSON.
12
+ */
13
+ function isJsonRequest(req) {
14
+ if (!req || !req.headers) return false;
15
+ const accept = (req.headers.accept || "").toLowerCase();
16
+ const xRequestedWith = (req.headers["x-requested-with"] || "").toLowerCase();
17
+ const userAgent = (req.headers["user-agent"] || "").toLowerCase();
18
+ const url = (req.originalUrl || req.url || "").toLowerCase();
19
+ const path = (req.path || "").toLowerCase();
20
+
21
+ const isApiPath = url.startsWith("/mbkauthe/api/") || url.startsWith("/api/") || path.startsWith("/mbkauthe/api/") || path.startsWith("/api/");
22
+ const isAcceptJson = accept.includes("application/json") || accept.includes("json") || accept.includes("*/*");
23
+
24
+ const nonBrowserAgent = /curl|wget|httpie|python-requests|python|go-http-client|java\/|php|node-fetch|axios|postman|insomnia|okhttp/;
25
+ const browserAgent = /mozilla|applewebkit|chrome|safari|firefox|edg|msie|trident|opera/;
26
+
27
+ if (isApiPath || xRequestedWith === "xmlhttprequest") return true;
28
+ if (isAcceptJson && !accept.includes("text/html")) return true;
29
+
30
+ if (nonBrowserAgent.test(userAgent) && !browserAgent.test(userAgent)) return true;
31
+
32
+ return false;
33
+ }
34
+
9
35
  /**
10
36
  * Validates a Bearer token (API Token or Session UUID)
11
37
  * Returns a user object if valid, or null/error object
@@ -160,6 +186,9 @@ async function validateSession(req, res, next, strictTokenValidation = false) {
160
186
  if (!req.session.user) {
161
187
  console.log("[mbkauthe] User not authenticated");
162
188
  console.log("[mbkauthe]: ", req.session.user);
189
+ if (isJsonRequest(req)) {
190
+ return res.status(401).json(createErrorResponse(401, ErrorCodes.SESSION_NOT_FOUND));
191
+ }
163
192
  return renderError(res, req, {
164
193
  code: 401,
165
194
  error: "Not Logged In",
@@ -177,6 +206,9 @@ async function validateSession(req, res, next, strictTokenValidation = false) {
177
206
  console.warn(`[mbkauthe] Missing sessionId for user "${req.session.user.username}"`);
178
207
  req.session.destroy();
179
208
  clearSessionCookies(res);
209
+ if (isJsonRequest(req)) {
210
+ return res.status(401).json(createErrorResponse(401, ErrorCodes.SESSION_EXPIRED));
211
+ }
180
212
  return renderError(res, req, {
181
213
  code: 401,
182
214
  error: "Session Expired",
@@ -200,6 +232,9 @@ async function validateSession(req, res, next, strictTokenValidation = false) {
200
232
  console.log(`[mbkauthe] Session not found for user "${req.session.user.username}"`);
201
233
  req.session.destroy();
202
234
  clearSessionCookies(res);
235
+ if (isJsonRequest(req)) {
236
+ return res.status(401).json(createErrorResponse(401, ErrorCodes.SESSION_EXPIRED));
237
+ }
203
238
  return renderError(res, req, {
204
239
  code: 401,
205
240
  error: "Session Expired",
@@ -217,6 +252,9 @@ async function validateSession(req, res, next, strictTokenValidation = false) {
217
252
  // destroy and clear cookies
218
253
  req.session.destroy();
219
254
  clearSessionCookies(res);
255
+ if (isJsonRequest(req)) {
256
+ return res.status(401).json(createErrorResponse(401, ErrorCodes.SESSION_EXPIRED));
257
+ }
220
258
  return renderError(res, req, {
221
259
  code: 401,
222
260
  error: "Session Expired",
@@ -231,6 +269,9 @@ async function validateSession(req, res, next, strictTokenValidation = false) {
231
269
  console.log(`[mbkauthe] Account is inactive for user "${req.session.user.username}"`);
232
270
  req.session.destroy();
233
271
  clearSessionCookies(res);
272
+ if (isJsonRequest(req)) {
273
+ return res.status(401).json(createErrorResponse(401, ErrorCodes.ACCOUNT_INACTIVE));
274
+ }
234
275
  return renderError(res, req, {
235
276
  code: 401,
236
277
  error: "Account Inactive",
@@ -247,6 +288,9 @@ async function validateSession(req, res, next, strictTokenValidation = false) {
247
288
  console.warn(`[mbkauthe] User \"${req.session.user.username}\" is not authorized to use the application \"${mbkautheVar.APP_NAME}\"`);
248
289
  req.session.destroy();
249
290
  clearSessionCookies(res);
291
+ if (isJsonRequest(req)) {
292
+ return res.status(401).json(createErrorResponse(401, ErrorCodes.APP_NOT_AUTHORIZED));
293
+ }
250
294
  return renderError(res, req, {
251
295
  code: 401,
252
296
  error: "Unauthorized",
@@ -444,6 +488,9 @@ const checkRolePermission = (requiredRoles, notAllowed) => {
444
488
  try {
445
489
  if (!req.session || !req.session.user || !req.session.user.id) {
446
490
  console.log("[mbkauthe] User not authenticated");
491
+ if (isJsonRequest(req)) {
492
+ return res.status(401).json(createErrorResponse(401, ErrorCodes.SESSION_NOT_FOUND));
493
+ }
447
494
  return renderError(res, req, {
448
495
  code: 401,
449
496
  error: "Not Logged In",
@@ -458,6 +505,9 @@ const checkRolePermission = (requiredRoles, notAllowed) => {
458
505
 
459
506
  // Check notAllowed role
460
507
  if (notAllowed && userRole === notAllowed) {
508
+ if (isJsonRequest(req)) {
509
+ return res.status(403).json(createErrorResponse(403, ErrorCodes.ROLE_NOT_ALLOWED));
510
+ }
461
511
  return renderError(res, req, {
462
512
  code: 403,
463
513
  error: "Access Denied",
@@ -477,6 +527,9 @@ const checkRolePermission = (requiredRoles, notAllowed) => {
477
527
 
478
528
  // Check if user role is in allowed roles
479
529
  if (!rolesArray.includes(userRole)) {
530
+ if (isJsonRequest(req)) {
531
+ return res.status(403).json(createErrorResponse(403, ErrorCodes.INSUFFICIENT_PERMISSIONS));
532
+ }
480
533
  return renderError(res, req, {
481
534
  code: 403,
482
535
  error: "Access Denied",
package/lib/pool.js CHANGED
@@ -12,14 +12,9 @@ const poolConfig = {
12
12
  ssl: {
13
13
  rejectUnauthorized: true,
14
14
  },
15
-
16
- // Connection pool tuning for serverless/ephemeral environments (Vercel)
17
- // - keep max small to avoid exhausting DB connections
18
- // - reduce idle time so connections are returned sooner
19
- // - set a short connection timeout to fail fast
20
- max: 10,
15
+ max: 3,
21
16
  idleTimeoutMillis: 10000,
22
- connectionTimeoutMillis: 25000,
17
+ connectionTimeoutMillis: 10000,
23
18
  };
24
19
 
25
20
  export const dblogin = new Pool(poolConfig);
@@ -27,6 +22,14 @@ export const dblogin = new Pool(poolConfig);
27
22
  // Keep pool.js focused on pool setup; attach dev-only query logger from dedicated module.
28
23
  attachDevQueryLogger(dblogin);
29
24
 
25
+ /*
26
+ attachDevQueryLogger([
27
+ { pool: dblogin, name: "loginDB" },
28
+ { pool: dblogin1, name: "loginDB1" },
29
+ ]);
30
+ */
31
+
32
+ /*
30
33
  (async () => {
31
34
  try {
32
35
  const client = await dblogin.connect();
@@ -34,4 +37,5 @@ attachDevQueryLogger(dblogin);
34
37
  } catch (err) {
35
38
  console.error("[mbkauthe] Database connection error (pool):", err);
36
39
  }
37
- })();
40
+ })();
41
+ */
@@ -1,6 +1,7 @@
1
1
  import express from "express";
2
2
  import { renderError } from "#response.js";
3
3
  import { dblogin } from "#pool.js";
4
+ import { getQueryCount, getQueryLog, resetQueryCount, resetQueryLog } from "../utils/dbQueryLogger.js";
4
5
  import { mbkautheVar } from "#config.js";
5
6
  import rateLimit from 'express-rate-limit';
6
7
 
@@ -39,8 +40,8 @@ router.get(["/db.json"], LogLimit, async (req, res) => {
39
40
  });
40
41
  }
41
42
 
42
- const queryCount = typeof dblogin.getQueryCount === 'function' ? dblogin.getQueryCount() : null;
43
- const queryLog = typeof dblogin.getQueryLog === 'function' ? dblogin.getQueryLog({ limit: queryLimit }) : [];
43
+ const queryCount = typeof getQueryCount === 'function' ? getQueryCount() : (typeof dblogin.getQueryCount === 'function' ? dblogin.getQueryCount() : 0);
44
+ const queryLog = typeof getQueryLog === 'function' ? getQueryLog({ limit: queryLimit }) : (typeof dblogin.getQueryLog === 'function' ? dblogin.getQueryLog({ limit: queryLimit }) : []);
44
45
 
45
46
  return res.json({ queryCount, queryLimit, queryLog, isDev });
46
47
  } catch (err) {
@@ -61,8 +62,11 @@ router.post(["/db/reset"], LogLimit, async (req, res) => {
61
62
  });
62
63
  }
63
64
 
64
- if (typeof dblogin.resetQueryCount === 'function') dblogin.resetQueryCount();
65
- if (typeof dblogin.resetQueryLog === 'function') dblogin.resetQueryLog();
65
+ if (typeof resetQueryCount === 'function') resetQueryCount();
66
+ else if (typeof dblogin.resetQueryCount === 'function') dblogin.resetQueryCount();
67
+
68
+ if (typeof resetQueryLog === 'function') resetQueryLog();
69
+ else if (typeof dblogin.resetQueryLog === 'function') dblogin.resetQueryLog();
66
70
 
67
71
  return res.json({ success: true, message: 'Query log and count have been reset.' });
68
72
  } catch (err) {