zet-lib 2.0.2 → 3.0.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/lib/csrf.js ADDED
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+
3
+ const crypto = require('crypto');
4
+
5
+ /**
6
+ * CSRF Protection Middleware
7
+ * Compatible with csurf API for easy migration
8
+ *
9
+ * @param {Object} options - Configuration options
10
+ * @param {Boolean} options.cookie - Use cookie-based storage (default: false, uses session)
11
+ * @param {String} options.cookieKey - Cookie name for secret (default: '_csrf')
12
+ * @param {String} options.value - Function to get token from request (default: reads from body/query/header)
13
+ * @param {Boolean} options.ignoreMethods - HTTP methods to ignore (default: ['GET', 'HEAD', 'OPTIONS'])
14
+ * @param {String} options.secretLength - Length of secret (default: 24)
15
+ */
16
+ function csrf(options = {}) {
17
+ const opts = {
18
+ cookie: options.cookie !== undefined ? options.cookie : false,
19
+ cookieKey: options.cookieKey || '_csrf',
20
+ value: options.value || defaultValue,
21
+ ignoreMethods: options.ignoreMethods || ['GET', 'HEAD', 'OPTIONS'],
22
+ secretLength: options.secretLength || 24
23
+ };
24
+
25
+ // Generate a secret for cookie-based storage
26
+ function generateSecret() {
27
+ return crypto.randomBytes(opts.secretLength).toString('base64');
28
+ }
29
+
30
+ // Generate CSRF token from secret
31
+ function generateToken(secret) {
32
+ return crypto
33
+ .createHash('sha1')
34
+ .update(secret + 'csrfSecret')
35
+ .digest('base64');
36
+ }
37
+
38
+ // Get secret from cookie or session
39
+ function getSecret(req) {
40
+ if (opts.cookie) {
41
+ return req.cookies && req.cookies[opts.cookieKey];
42
+ } else {
43
+ return req.session && req.session._csrfSecret;
44
+ }
45
+ }
46
+
47
+ // Set secret in cookie or session
48
+ function setSecret(req, res, secret) {
49
+ if (opts.cookie) {
50
+ // Set cookie if not already set
51
+ if (!req.cookies || !req.cookies[opts.cookieKey]) {
52
+ res.cookie(opts.cookieKey, secret, {
53
+ httpOnly: true,
54
+ secure: process.env.NODE_ENV === 'production',
55
+ sameSite: 'strict',
56
+ maxAge: 86400000 // 24 hours
57
+ });
58
+ // Also set in req.cookies for immediate access
59
+ if (!req.cookies) {
60
+ req.cookies = {};
61
+ }
62
+ req.cookies[opts.cookieKey] = secret;
63
+ }
64
+ } else {
65
+ if (!req.session) {
66
+ throw new Error('Session is required when cookie option is false');
67
+ }
68
+ if (!req.session._csrfSecret) {
69
+ req.session._csrfSecret = secret;
70
+ }
71
+ }
72
+ }
73
+
74
+ // Default function to get token from request
75
+ function defaultValue(req) {
76
+ return (req.body && req.body._csrf) ||
77
+ (req.query && req.query._csrf) ||
78
+ (req.headers['csrf-token']) ||
79
+ (req.headers['xsrf-token']) ||
80
+ (req.headers['x-csrf-token']) ||
81
+ (req.headers['x-xsrf-token']);
82
+ }
83
+
84
+ // Middleware function
85
+ return function csrfMiddleware(req, res, next) {
86
+ // Get or create secret
87
+ let secret = getSecret(req);
88
+ if (!secret) {
89
+ secret = generateSecret();
90
+ setSecret(req, res, secret);
91
+ }
92
+
93
+ // Attach csrfToken method to request
94
+ req.csrfToken = function csrfToken() {
95
+ return generateToken(getSecret(req));
96
+ };
97
+
98
+ // Skip CSRF validation for ignored methods
99
+ if (opts.ignoreMethods.indexOf(req.method) !== -1) {
100
+ return next();
101
+ }
102
+
103
+ // Skip CSRF validation for AJAX calls (X-Requested-With header)
104
+ // This allows AJAX calls without token refresh
105
+ if (req.headers['x-requested-with'] === 'XMLHttpRequest' || req.xhr) {
106
+ return next();
107
+ }
108
+
109
+ // Get token from request
110
+ const token = opts.value(req);
111
+ const secretValue = getSecret(req);
112
+ const expectedToken = generateToken(secretValue);
113
+
114
+ // Validate token
115
+ if (!token || token !== expectedToken) {
116
+ const err = new Error('Invalid CSRF token');
117
+ err.status = 403;
118
+ err.code = 'EBADCSRFTOKEN';
119
+ return next(err);
120
+ }
121
+
122
+ // Token is valid, continue
123
+ next();
124
+ };
125
+ }
126
+
127
+ // Export the csrf function
128
+ module.exports = csrf;
129
+
@@ -3,7 +3,7 @@ const router = express.Router();
3
3
  const generatorApp = require("./generatorApp");
4
4
  const configGenerator = require('./config_generator');
5
5
 
6
- const csrf = require('csurf');
6
+ const csrf = require('./csrf');
7
7
  const Model = require("./Model");
8
8
  const fs = require('fs-extra');
9
9
  //const {connection, Util} = require('zet-lib');
package/lib/index.js CHANGED
@@ -28,7 +28,8 @@ const coreModules = {
28
28
  zPage: require("./zPage"),
29
29
  zTester: require("./zTester"),
30
30
  zCache: require("./zCache"),
31
- zDropbox: require("./zDropbox")
31
+ zDropbox: require("./zDropbox"),
32
+ csrf: require("./csrf")
32
33
  };
33
34
 
34
35
  // Heavy dependencies - lazy loaded (only when accessed)
@@ -1,5 +1,5 @@
1
1
  const router = require('express').Router();
2
- const csrf = require('csurf');
2
+ const {csrf} = require('zet-lib');
3
3
  const csrfProtection = csrf({cookie: true});
4
4
  const {Util, access, connection, moduleLib, zDebug, zRoute, zRole, zDataTable, zForm} = require('zet-lib');
5
5
  const MYMODEL = require('./../models/[[[TABLE_NAME]]]');
@@ -1,5 +1,5 @@
1
1
  const router = require('express').Router();
2
- const csrf = require('csurf');
2
+ const {csrf} = require('zet-lib');
3
3
  const csrfProtection = csrf({cookie: true});
4
4
  const {Util, access, connection, moduleLib, zDebug, zRoute, zRole, zDataTable, zForm} = require('zet-lib');
5
5
  const MYMODEL = require('./../models/[[[TABLE_NAME]]]');
package/lib/zAppRouter.js CHANGED
@@ -1,7 +1,7 @@
1
1
  require("dotenv").config();
2
2
  const express = require("express");
3
3
  const router = express.Router();
4
- const csrf = require("csurf");
4
+ const csrf = require("./csrf");
5
5
  const csrfProtection = csrf({ cookie: true });
6
6
  const zRoute = require("./zRoute");
7
7
  const connection = require("./connection");
@@ -1,6 +1,6 @@
1
1
  const express = require("express");
2
2
  const router = express.Router();
3
- const csrf = require("csurf");
3
+ const csrf = require("./csrf");
4
4
  const csrfProtection = csrf({ cookie: true });
5
5
  const fs = require("fs-extra");
6
6
  const axios = require("axios");
@@ -1,6 +1,6 @@
1
1
  const express = require('express');
2
2
  const router = express.Router();
3
- const csrf = require('csurf');
3
+ const csrf = require('./csrf');
4
4
  const csrfProtection = csrf({cookie: true});
5
5
  const fs = require('fs-extra');
6
6
  //const {Util, connection, zRole, zCache } = require('zet-lib');
package/lib/zPage.js CHANGED
@@ -52,7 +52,7 @@ zpage.build = async (req, res) => {
52
52
 
53
53
  zpage.coreCode = () => {
54
54
  return `const router = require('express').Router();
55
- const csrf = require('csurf');
55
+ const {csrf} = require('zet-lib');
56
56
  const csrfProtection = csrf({cookie: true});
57
57
  const fs = require('fs-extra');
58
58
  const qs = require('qs');
@@ -1,7 +1,7 @@
1
1
  const express = require('express')
2
2
  const router = express.Router()
3
3
  // setup route middlewares
4
- const csrf = require('csurf')
4
+ const csrf = require('./csrf')
5
5
  const bodyParser = require('body-parser')
6
6
  const path = require('path')
7
7
  const parseForm = bodyParser.urlencoded({ extended: true })
@@ -1,6 +1,6 @@
1
1
  const express = require('express');
2
2
  const router = express.Router();
3
- const csrf = require('csurf');
3
+ const csrf = require('./csrf');
4
4
  const csrfProtection = csrf({cookie: true});
5
5
  const fs = require("fs-extra");
6
6
  const Util = require("./Util");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zet-lib",
3
- "version": "2.0.2",
3
+ "version": "3.0.0",
4
4
  "description": "zet is a library that part of zet generator.",
5
5
  "engines": {
6
6
  "node": ">=18"
@@ -30,7 +30,6 @@
30
30
  "dependencies": {
31
31
  "axios": "^1.7.9",
32
32
  "convert-excel-to-json": "^1.7.0",
33
- "csurf": "^1.11.0",
34
33
  "dotenv": "^16.5.0",
35
34
  "dropbox": "^10.34.0",
36
35
  "ejs": "^3.1.10",