hfs 0.26.7 → 0.26.8

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.
Files changed (162) hide show
  1. package/admin/.DS_Store +0 -0
  2. package/admin/.eslintrc +8 -0
  3. package/admin/.gitignore +23 -0
  4. package/admin/index.html +1 -3
  5. package/admin/package.json +67 -0
  6. package/admin/{logo.svg → public/logo.svg} +0 -0
  7. package/admin/src/AccountForm.ts +92 -0
  8. package/admin/src/AccountsPage.ts +143 -0
  9. package/admin/src/App.ts +83 -0
  10. package/admin/src/ArrayField.ts +84 -0
  11. package/admin/src/ConfigPage.ts +279 -0
  12. package/admin/src/FileField.ts +52 -0
  13. package/admin/src/FileForm.ts +148 -0
  14. package/admin/src/FilePicker.ts +166 -0
  15. package/admin/src/HomePage.ts +96 -0
  16. package/admin/src/InstalledPlugins.ts +158 -0
  17. package/admin/src/LoginRequired.ts +75 -0
  18. package/admin/src/LogoutPage.ts +27 -0
  19. package/admin/src/LogsPage.ts +75 -0
  20. package/admin/src/MainMenu.ts +74 -0
  21. package/admin/src/MenuButton.ts +38 -0
  22. package/admin/src/MonitorPage.ts +200 -0
  23. package/admin/src/OnlinePlugins.ts +101 -0
  24. package/admin/src/PermField.ts +80 -0
  25. package/admin/src/PluginsPage.ts +27 -0
  26. package/admin/src/VfsMenuBar.ts +58 -0
  27. package/admin/src/VfsPage.ts +124 -0
  28. package/admin/src/VfsTree.ts +95 -0
  29. package/admin/src/addFiles.ts +59 -0
  30. package/admin/src/api.ts +246 -0
  31. package/admin/src/dialog.ts +203 -0
  32. package/admin/src/index.css +21 -0
  33. package/admin/src/index.ts +10 -0
  34. package/admin/src/md.ts +31 -0
  35. package/admin/src/misc.ts +141 -0
  36. package/admin/src/react-app-env.d.ts +1 -0
  37. package/admin/src/reportWebVitals.ts +15 -0
  38. package/admin/src/setupTests.ts +5 -0
  39. package/admin/src/state.ts +40 -0
  40. package/admin/src/theme.ts +37 -0
  41. package/admin/tsconfig.json +26 -0
  42. package/admin/vite.config.ts +32 -0
  43. package/frontend/.DS_Store +0 -0
  44. package/frontend/.eslintrc +8 -0
  45. package/frontend/.gitignore +23 -0
  46. package/frontend/index.html +1 -3
  47. package/frontend/package.json +51 -0
  48. package/frontend/{fontello.css → public/fontello.css} +0 -0
  49. package/frontend/{fontello.woff2 → public/fontello.woff2} +0 -0
  50. package/frontend/src/App.ts +25 -0
  51. package/frontend/src/Breadcrumbs.ts +43 -0
  52. package/frontend/src/BrowseFiles.ts +141 -0
  53. package/frontend/src/Head.ts +45 -0
  54. package/frontend/src/UserPanel.ts +52 -0
  55. package/frontend/src/api.ts +78 -0
  56. package/frontend/src/components.ts +54 -0
  57. package/frontend/src/dialog.css +76 -0
  58. package/frontend/src/dialog.ts +105 -0
  59. package/frontend/src/icons.ts +46 -0
  60. package/frontend/src/index.scss +307 -0
  61. package/frontend/src/index.ts +10 -0
  62. package/frontend/src/login.ts +50 -0
  63. package/frontend/src/menu.ts +188 -0
  64. package/frontend/src/misc.ts +54 -0
  65. package/frontend/src/options.ts +52 -0
  66. package/frontend/src/react-app-env.d.ts +1 -0
  67. package/frontend/src/reportWebVitals.ts +15 -0
  68. package/frontend/src/setupTests.ts +5 -0
  69. package/frontend/src/state.ts +82 -0
  70. package/frontend/src/useAuthorized.ts +17 -0
  71. package/frontend/src/useFetchList.ts +144 -0
  72. package/frontend/src/useTheme.ts +23 -0
  73. package/frontend/tsconfig.json +26 -0
  74. package/frontend/vite.config.ts +21 -0
  75. package/package.json +2 -1
  76. package/plugins/vhosting/plugin.js +1 -1
  77. package/src/QuickZipStream.ts +279 -0
  78. package/src/ThrottledStream.ts +98 -0
  79. package/src/adminApis.ts +161 -0
  80. package/src/api.accounts.ts +78 -0
  81. package/src/api.auth.ts +131 -0
  82. package/src/api.file_list.ts +102 -0
  83. package/src/api.helpers.ts +30 -0
  84. package/src/api.monitor.ts +106 -0
  85. package/src/api.plugins.ts +139 -0
  86. package/src/api.vfs.ts +182 -0
  87. package/src/apiMiddleware.ts +124 -0
  88. package/src/block.ts +35 -0
  89. package/src/commands.ts +122 -0
  90. package/src/config.ts +166 -0
  91. package/src/connections.ts +60 -0
  92. package/src/const.ts +57 -0
  93. package/src/crypt.ts +16 -0
  94. package/src/debounceAsync.ts +51 -0
  95. package/src/events.ts +6 -0
  96. package/src/frontEndApis.ts +17 -0
  97. package/src/github.ts +102 -0
  98. package/src/index.ts +53 -0
  99. package/src/listen.ts +220 -0
  100. package/src/log.ts +128 -0
  101. package/src/middlewares.ts +176 -0
  102. package/src/misc.ts +149 -0
  103. package/src/pbkdf2.ts +83 -0
  104. package/src/perm.ts +194 -0
  105. package/src/plugins.ts +342 -0
  106. package/src/serveFile.ts +104 -0
  107. package/src/serveGuiFiles.ts +95 -0
  108. package/src/sse.ts +29 -0
  109. package/src/throttler.ts +106 -0
  110. package/src/update.ts +67 -0
  111. package/src/util-files.ts +137 -0
  112. package/src/util-generators.ts +29 -0
  113. package/src/util-http.ts +29 -0
  114. package/src/vfs.ts +258 -0
  115. package/src/watchLoad.ts +75 -0
  116. package/src/zip.ts +69 -0
  117. package/admin/assets/index.0f549e00.js +0 -281
  118. package/admin/assets/index.dcc78777.css +0 -1
  119. package/admin/assets/sha512.ea1121b3.js +0 -8
  120. package/frontend/assets/index.1151988f.js +0 -85
  121. package/frontend/assets/index.93366732.css +0 -1
  122. package/frontend/assets/sha512.bb881250.js +0 -8
  123. package/src/QuickZipStream.js +0 -285
  124. package/src/ThrottledStream.js +0 -93
  125. package/src/adminApis.js +0 -169
  126. package/src/api.accounts.js +0 -59
  127. package/src/api.auth.js +0 -130
  128. package/src/api.file_list.js +0 -103
  129. package/src/api.helpers.js +0 -32
  130. package/src/api.monitor.js +0 -102
  131. package/src/api.plugins.js +0 -127
  132. package/src/api.vfs.js +0 -164
  133. package/src/apiMiddleware.js +0 -136
  134. package/src/block.js +0 -33
  135. package/src/commands.js +0 -124
  136. package/src/config.js +0 -168
  137. package/src/connections.js +0 -57
  138. package/src/const.js +0 -83
  139. package/src/crypt.js +0 -21
  140. package/src/debounceAsync.js +0 -48
  141. package/src/events.js +0 -9
  142. package/src/frontEndApis.js +0 -38
  143. package/src/github.js +0 -102
  144. package/src/index.js +0 -55
  145. package/src/listen.js +0 -235
  146. package/src/log.js +0 -137
  147. package/src/middlewares.js +0 -154
  148. package/src/misc.js +0 -160
  149. package/src/pbkdf2.js +0 -74
  150. package/src/perm.js +0 -176
  151. package/src/plugins.js +0 -343
  152. package/src/serveFile.js +0 -104
  153. package/src/serveGuiFiles.js +0 -113
  154. package/src/sse.js +0 -29
  155. package/src/throttler.js +0 -91
  156. package/src/update.js +0 -69
  157. package/src/util-files.js +0 -148
  158. package/src/util-generators.js +0 -30
  159. package/src/util-http.js +0 -30
  160. package/src/vfs.js +0 -227
  161. package/src/watchLoad.js +0 -73
  162. package/src/zip.js +0 -69
package/src/log.js DELETED
@@ -1,137 +0,0 @@
1
- "use strict";
2
- // This file is part of HFS - Copyright 2021-2022, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
3
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
- if (k2 === undefined) k2 = k;
5
- var desc = Object.getOwnPropertyDescriptor(m, k);
6
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
- desc = { enumerable: true, get: function() { return m[k]; } };
8
- }
9
- Object.defineProperty(o, k2, desc);
10
- }) : (function(o, m, k, k2) {
11
- if (k2 === undefined) k2 = k;
12
- o[k2] = m[k];
13
- }));
14
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
- Object.defineProperty(o, "default", { enumerable: true, value: v });
16
- }) : function(o, v) {
17
- o["default"] = v;
18
- });
19
- var __importStar = (this && this.__importStar) || function (mod) {
20
- if (mod && mod.__esModule) return mod;
21
- var result = {};
22
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
23
- __setModuleDefault(result, mod);
24
- return result;
25
- };
26
- var __importDefault = (this && this.__importDefault) || function (mod) {
27
- return (mod && mod.__esModule) ? mod : { "default": mod };
28
- };
29
- Object.defineProperty(exports, "__esModule", { value: true });
30
- exports.log = exports.loggers = void 0;
31
- const config_1 = require("./config");
32
- const fs_1 = require("fs");
33
- const util = __importStar(require("util"));
34
- const promises_1 = require("fs/promises");
35
- const const_1 = require("./const");
36
- const events_1 = __importDefault(require("./events"));
37
- const lodash_1 = __importDefault(require("lodash"));
38
- const path_1 = require("path");
39
- const perm_1 = require("./perm");
40
- class Logger {
41
- constructor(name) {
42
- this.name = name;
43
- this.path = '';
44
- }
45
- async setPath(path) {
46
- var _a;
47
- this.path = path;
48
- (_a = this.stream) === null || _a === void 0 ? void 0 : _a.end();
49
- this.last = undefined;
50
- if (!path)
51
- return this.stream = undefined;
52
- try {
53
- const stats = await (0, promises_1.stat)(path);
54
- this.last = stats.mtime || stats.ctime;
55
- }
56
- catch (_b) {
57
- await (0, promises_1.mkdir)((0, path_1.dirname)(path), { recursive: true })
58
- .catch(() => console.log("cannot create folder for", path));
59
- }
60
- this.reopen();
61
- }
62
- reopen() {
63
- return this.stream = (0, fs_1.createWriteStream)(this.path, { flags: 'a' })
64
- .on('error', () => this.stream = undefined);
65
- }
66
- }
67
- // we'll have names same as config keys. These are used also by the get_log api.
68
- const accessLogger = new Logger('log');
69
- const accessErrorLog = new Logger('error_log');
70
- exports.loggers = [accessLogger, accessErrorLog];
71
- (0, config_1.defineConfig)('log', 'logs/access.log').sub(path => {
72
- console.debug('access log file: ' + (path || 'disabled'));
73
- accessLogger.setPath(path);
74
- });
75
- const errorLogFile = (0, config_1.defineConfig)(accessErrorLog.name, 'logs/access-error.log');
76
- errorLogFile.sub(path => {
77
- console.debug('access error log: ' + (path || 'disabled'));
78
- accessErrorLog.setPath(path);
79
- });
80
- const logRotation = (0, config_1.defineConfig)('log_rotation', 'weekly');
81
- function log() {
82
- const debounce = lodash_1.default.debounce(cb => cb(), 1000);
83
- return async (ctx, next) => {
84
- var _a;
85
- await next();
86
- const isError = ctx.status >= 400;
87
- const logger = isError && accessErrorLog || accessLogger;
88
- const rotate = (_a = logRotation.get()) === null || _a === void 0 ? void 0 : _a[0];
89
- let { stream, last, path } = logger;
90
- if (!stream)
91
- return;
92
- const now = new Date();
93
- const a = now.toString().split(' ');
94
- logger.last = now;
95
- if (rotate && last) { // rotation enabled and a file exists?
96
- const passed = Number(now) - Number(last)
97
- - 3600000; // be pessimistic and count a possible DST change
98
- if (rotate === 'm' && (passed >= 31 * const_1.DAY || now.getMonth() !== last.getMonth())
99
- || rotate === 'd' && (passed >= const_1.DAY || now.getDate() !== last.getDate()) // checking passed will solve the case when the day of the month is the same but a month has passed
100
- || rotate === 'w' && (passed >= 7 * const_1.DAY || now.getDay() < last.getDay())) {
101
- stream.end();
102
- const postfix = last.getFullYear() + '-' + doubleDigit(last.getMonth() + 1) + '-' + doubleDigit(last.getDate());
103
- try { // other logging requests shouldn't happen while we are renaming. Since this is very infrequent we can tolerate solving this by making it sync.
104
- (0, fs_1.renameSync)(path, path + '-' + postfix);
105
- }
106
- catch (e) { // ok, rename failed, but this doesn't mean we ain't gonna log
107
- console.error(e);
108
- }
109
- stream = logger.reopen(); // keep variable updated
110
- if (!stream)
111
- return;
112
- }
113
- }
114
- const format = '%s - %s [%s] "%s %s HTTP/%s" %d %s\n'; // Apache's Common Log Format
115
- const date = a[2] + '/' + a[1] + '/' + a[3] + ':' + a[4] + ' ' + a[5].slice(3);
116
- const user = (0, perm_1.getCurrentUsername)(ctx);
117
- events_1.default.emit(logger.name, Object.assign(lodash_1.default.pick(ctx, ['ip', 'method', 'status', 'length']), { user, ts: now, uri: ctx.path }));
118
- console.debug(ctx.status, ctx.method, ctx.path);
119
- debounce(() => // once in a while we check if the file is still good (not deleted, etc), or we'll reopen it
120
- (0, promises_1.stat)(logger.path).catch(() => logger.reopen())); // async = smoother but we may lose some entries
121
- stream.write(util.format(format, ctx.ip, user || '-', date, ctx.method, ctx.path, ctx.req.httpVersion, ctx.status, ctx.length ? ctx.length.toString() : '-'));
122
- };
123
- }
124
- exports.log = log;
125
- function doubleDigit(n) {
126
- return n > 9 ? n : '0' + n;
127
- }
128
- // dump console.error to file
129
- const debugLogFile = (0, fs_1.createWriteStream)('debug.log', { flags: 'a' });
130
- debugLogFile.on('open', () => {
131
- const was = console.error;
132
- console.error = function (...args) {
133
- was.apply(this, args);
134
- const params = args.map(x => typeof x === 'string' ? x : JSON.stringify(x)).join(' ');
135
- debugLogFile.write(new Date().toLocaleString() + ': ' + params + '\n');
136
- };
137
- }).on('error', () => console.log("cannot create debug.log"));
@@ -1,154 +0,0 @@
1
- "use strict";
2
- // This file is part of HFS - Copyright 2021-2022, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
3
- var __importDefault = (this && this.__importDefault) || function (mod) {
4
- return (mod && mod.__esModule) ? mod : { "default": mod };
5
- };
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.prepareState = exports.getProxyDetected = exports.someSecurity = exports.serveGuiAndSharedFiles = exports.sessions = exports.headRequests = exports.gzipper = void 0;
8
- const koa_compress_1 = __importDefault(require("koa-compress"));
9
- const koa_session_1 = __importDefault(require("koa-session"));
10
- const const_1 = require("./const");
11
- const const_2 = require("./const");
12
- const vfs_1 = require("./vfs");
13
- const misc_1 = require("./misc");
14
- const zip_1 = require("./zip");
15
- const serveFile_1 = require("./serveFile");
16
- const serveGuiFiles_1 = require("./serveGuiFiles");
17
- const koa_mount_1 = __importDefault(require("koa-mount"));
18
- const stream_1 = require("stream");
19
- const block_1 = require("./block");
20
- const perm_1 = require("./perm");
21
- const connections_1 = require("./connections");
22
- const basic_auth_1 = __importDefault(require("basic-auth"));
23
- const tssrp6a_1 = require("tssrp6a");
24
- const api_auth_1 = require("./api.auth");
25
- exports.gzipper = (0, koa_compress_1.default)({
26
- threshold: 2048,
27
- gzip: { flush: require('zlib').constants.Z_SYNC_FLUSH },
28
- deflate: { flush: require('zlib').constants.Z_SYNC_FLUSH },
29
- br: false,
30
- filter(type) {
31
- return /text|javascript|style/i.test(type);
32
- },
33
- });
34
- const headRequests = async (ctx, next) => {
35
- const head = ctx.method === 'HEAD';
36
- if (head)
37
- ctx.method = 'GET'; // let other middlewares work, so we can collect the size at the end
38
- await next();
39
- if (!head || ctx.body === undefined)
40
- return;
41
- const { length, status } = ctx.response;
42
- if (ctx.body)
43
- ctx.body = stream_1.Readable.from(''); // empty the body for this is a HEAD request. Using Readable avoids koa from trying to set length to 0
44
- ctx.status = status;
45
- if (length)
46
- ctx.response.length = length;
47
- };
48
- exports.headRequests = headRequests;
49
- const sessions = (app) => (0, koa_session_1.default)({
50
- key: 'hfs_$id',
51
- signed: true,
52
- rolling: true,
53
- maxAge: const_1.SESSION_DURATION,
54
- }, app);
55
- exports.sessions = sessions;
56
- const serveFrontendFiles = (0, serveGuiFiles_1.serveGuiFiles)(process.env.FRONTEND_PROXY, const_2.FRONTEND_URI);
57
- const serveFrontendPrefixed = (0, koa_mount_1.default)(const_2.FRONTEND_URI.slice(0, -1), serveFrontendFiles);
58
- const serveAdminPrefixed = (0, koa_mount_1.default)(const_1.ADMIN_URI.slice(0, -1), (0, serveGuiFiles_1.serveGuiFiles)(process.env.ADMIN_PROXY, const_1.ADMIN_URI));
59
- const serveGuiAndSharedFiles = async (ctx, next) => {
60
- const { path } = ctx;
61
- if (ctx.body)
62
- return next();
63
- if (path.startsWith(const_2.FRONTEND_URI))
64
- return serveFrontendPrefixed(ctx, next);
65
- if (path + '/' === const_1.ADMIN_URI)
66
- return ctx.redirect(const_1.ADMIN_URI);
67
- if (path.startsWith(const_1.ADMIN_URI))
68
- return serveAdminPrefixed(ctx, next);
69
- const node = await (0, vfs_1.urlToNode)(path, ctx);
70
- if (!node)
71
- return ctx.status = 404;
72
- const canRead = (0, vfs_1.hasPermission)(node, 'can_read', ctx);
73
- const isFolder = await (0, vfs_1.nodeIsDirectory)(node);
74
- if (isFolder && !path.endsWith('/'))
75
- return ctx.redirect(path + '/');
76
- if (canRead && !isFolder)
77
- return node.source ? (0, serveFile_1.serveFileNode)(node)(ctx, next)
78
- : next();
79
- if (!canRead) {
80
- ctx.status = (0, vfs_1.cantReadStatusCode)(node);
81
- if (ctx.status === const_1.FORBIDDEN)
82
- return;
83
- const browserDetected = ctx.get('Upgrade-Insecure-Requests') || ctx.get('Sec-Fetch-Mode'); // ugh, heuristics
84
- if (!browserDetected) // we don't want to trigger basic authentication on browsers, it's meant for download managers only
85
- ctx.set('WWW-Authenticate', 'Basic'); // we support basic authentication
86
- ctx.state.serveApp = true;
87
- return serveFrontendFiles(ctx, next);
88
- }
89
- ctx.set({ server: 'HFS ' + const_1.BUILD_TIMESTAMP });
90
- const { get } = ctx.query;
91
- if (get === 'zip')
92
- return await (0, zip_1.zipStreamFromFolder)(node, ctx);
93
- if (node.default) {
94
- const def = await (0, vfs_1.urlToNode)(path + node.default, ctx);
95
- return !def ? next()
96
- : (0, vfs_1.hasPermission)(def, 'can_read', ctx) ? (0, serveFile_1.serveFileNode)(def)(ctx, next)
97
- : ctx.status = (0, vfs_1.cantReadStatusCode)(def);
98
- }
99
- return serveFrontendFiles(ctx, next);
100
- };
101
- exports.serveGuiAndSharedFiles = serveGuiAndSharedFiles;
102
- let proxyDetected = false;
103
- const someSecurity = async (ctx, next) => {
104
- ctx.request.ip = (0, connections_1.normalizeIp)(ctx.ip);
105
- try {
106
- let proxy = ctx.get('X-Forwarded-For');
107
- // we have some dev-proxies to ignore
108
- if (const_1.DEV && proxy && [process.env.FRONTEND_PROXY, process.env.ADMIN_PROXY].includes(ctx.get('X-Forwarded-port')))
109
- proxy = '';
110
- if ((0, misc_1.dirTraversal)(decodeURI(ctx.path)))
111
- return ctx.status = 418;
112
- if ((0, block_1.applyBlock)(ctx.socket, ctx.ip))
113
- return;
114
- proxyDetected || (proxyDetected = proxy > '');
115
- ctx.state.proxiedFor = proxy;
116
- }
117
- catch (_a) {
118
- return ctx.status = 418;
119
- }
120
- return next();
121
- };
122
- exports.someSecurity = someSecurity;
123
- // this is only about http proxies
124
- function getProxyDetected() {
125
- return proxyDetected;
126
- }
127
- exports.getProxyDetected = getProxyDetected;
128
- const prepareState = async (ctx, next) => {
129
- var _a;
130
- // calculate these once and for all
131
- ctx.state.account = (_a = await getHttpAccount(ctx)) !== null && _a !== void 0 ? _a : (0, perm_1.getAccount)((0, perm_1.getCurrentUsername)(ctx));
132
- const conn = ctx.state.connection = (0, connections_1.socket2connection)(ctx.socket);
133
- await next();
134
- if (conn)
135
- (0, connections_1.updateConnection)(conn, { ctx });
136
- };
137
- exports.prepareState = prepareState;
138
- async function getHttpAccount(ctx) {
139
- const credentials = (0, basic_auth_1.default)(ctx.req);
140
- const account = (0, perm_1.getAccount)((credentials === null || credentials === void 0 ? void 0 : credentials.name) || '');
141
- if (account && await srpCheck(account.username, credentials.pass))
142
- return account;
143
- }
144
- async function srpCheck(username, password) {
145
- username = username.toLocaleLowerCase();
146
- const account = (0, perm_1.getAccount)(username);
147
- if (!(account === null || account === void 0 ? void 0 : account.srp) || !password)
148
- return false;
149
- const { step1, salt, pubKey } = await (0, api_auth_1.srpStep1)(account);
150
- const client = new tssrp6a_1.SRPClientSession(new tssrp6a_1.SRPRoutines(new tssrp6a_1.SRPParameters()));
151
- const clientRes1 = await client.step1(username, password);
152
- const clientRes2 = await clientRes1.step2(BigInt(salt), BigInt(pubKey));
153
- return await step1.step2(clientRes2.A, clientRes2.M1).then(() => true, () => false);
154
- }
package/src/misc.js DELETED
@@ -1,160 +0,0 @@
1
- "use strict";
2
- // This file is part of HFS - Copyright 2021-2022, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
3
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
- if (k2 === undefined) k2 = k;
5
- var desc = Object.getOwnPropertyDescriptor(m, k);
6
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
- desc = { enumerable: true, get: function() { return m[k]; } };
8
- }
9
- Object.defineProperty(o, k2, desc);
10
- }) : (function(o, m, k, k2) {
11
- if (k2 === undefined) k2 = k;
12
- o[k2] = m[k];
13
- }));
14
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
16
- };
17
- var __importDefault = (this && this.__importDefault) || function (mod) {
18
- return (mod && mod.__esModule) ? mod : { "default": mod };
19
- };
20
- Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.tryJson = exports.same = exports.isLocalHost = exports.with_ = exports.typedKeys = exports.objRenameKey = exports.onOff = exports.pendingPromise = exports.onlyTruthy = exports.truthy = exports.pattern2filter = exports.onFirstEvent = exports.onProcessExit = exports.randomId = exports.getOrSet = exports.wantArray = exports.wait = exports.objSameKeys = exports.setHidden = exports.prefix = exports.enforceFinal = exports.debounceAsync = void 0;
22
- const path_1 = require("path");
23
- const lodash_1 = __importDefault(require("lodash"));
24
- const assert_1 = __importDefault(require("assert"));
25
- __exportStar(require("./util-http"), exports);
26
- __exportStar(require("./util-generators"), exports);
27
- __exportStar(require("./util-files"), exports);
28
- const debounceAsync_1 = __importDefault(require("./debounceAsync"));
29
- exports.debounceAsync = debounceAsync_1.default;
30
- function enforceFinal(sub, s) {
31
- return s.endsWith(sub) ? s : s + sub;
32
- }
33
- exports.enforceFinal = enforceFinal;
34
- function prefix(pre, v, post = '') {
35
- return v ? pre + v + post : '';
36
- }
37
- exports.prefix = prefix;
38
- function setHidden(dest, src) {
39
- return Object.defineProperties(dest, objSameKeys(src, value => ({
40
- enumerable: false,
41
- writable: true,
42
- value,
43
- })));
44
- }
45
- exports.setHidden = setHidden;
46
- function objSameKeys(src, newValue) {
47
- return Object.fromEntries(Object.entries(src).map(([k, v]) => [k, newValue(v, k)]));
48
- }
49
- exports.objSameKeys = objSameKeys;
50
- function wait(ms) {
51
- return new Promise(res => setTimeout(res, ms));
52
- }
53
- exports.wait = wait;
54
- function wantArray(x) {
55
- return x == null ? [] : Array.isArray(x) ? x : [x];
56
- }
57
- exports.wantArray = wantArray;
58
- function getOrSet(o, k, creator) {
59
- return k in o ? o[k]
60
- : (o[k] = creator());
61
- }
62
- exports.getOrSet = getOrSet;
63
- // 10 chars is 51+bits, 8 is 41+bits
64
- function randomId(len = 10) {
65
- if (len > 10)
66
- return randomId(10) + randomId(len - 10);
67
- return Math.random()
68
- .toString(36)
69
- .substring(2, 2 + len)
70
- .replace(/l/g, 'L'); // avoid confusion reading l1
71
- }
72
- exports.randomId = randomId;
73
- const cbs = new Set();
74
- function onProcessExit(cb) {
75
- cbs.add(cb);
76
- return () => cbs.delete(cb);
77
- }
78
- exports.onProcessExit = onProcessExit;
79
- onFirstEvent(process, ['exit', 'SIGQUIT', 'SIGTERM', 'SIGINT', 'SIGHUP'], signal => Promise.allSettled(Array.from(cbs).map(cb => cb(signal))).then(() => process.exit(0)));
80
- function onFirstEvent(emitter, events, cb) {
81
- let already = false;
82
- for (const e of events)
83
- emitter.on(e, (...args) => {
84
- if (already)
85
- return;
86
- already = true;
87
- cb(...args);
88
- });
89
- }
90
- exports.onFirstEvent = onFirstEvent;
91
- function pattern2filter(pattern) {
92
- const re = new RegExp(lodash_1.default.escapeRegExp(pattern), 'i');
93
- return (s) => !s || !pattern || re.test((0, path_1.basename)(s));
94
- }
95
- exports.pattern2filter = pattern2filter;
96
- function truthy(value) {
97
- return Boolean(value);
98
- }
99
- exports.truthy = truthy;
100
- function onlyTruthy(arr) {
101
- return arr.filter(truthy);
102
- }
103
- exports.onlyTruthy = onlyTruthy;
104
- function pendingPromise() {
105
- let takeOut;
106
- const ret = new Promise((resolve, reject) => takeOut = { resolve, reject });
107
- return Object.assign(ret, takeOut);
108
- }
109
- exports.pendingPromise = pendingPromise;
110
- // install multiple handlers and returns a handy 'uninstall' function which requires no parameter. Pass a map {event:handler}
111
- function onOff(em, events) {
112
- events = { ...events }; // avoid later modifications, as we need this later for uninstallation
113
- for (const [k, cb] of Object.entries(events))
114
- for (const e of k.split(' '))
115
- em.on(e, cb);
116
- return () => {
117
- for (const [k, cb] of Object.entries(events))
118
- for (const e of k.split(' '))
119
- em.off(e, cb);
120
- };
121
- }
122
- exports.onOff = onOff;
123
- function objRenameKey(o, from, to) {
124
- if (!o || !o.hasOwnProperty(from) || from === to)
125
- return;
126
- o[to] = o[from];
127
- delete o[from];
128
- return true;
129
- }
130
- exports.objRenameKey = objRenameKey;
131
- function typedKeys(o) {
132
- return Object.keys(o);
133
- }
134
- exports.typedKeys = typedKeys;
135
- function with_(par, cb) {
136
- return cb(par);
137
- }
138
- exports.with_ = with_;
139
- function isLocalHost(c) {
140
- const ip = c.socket.remoteAddress; // don't use Context.ip as it is subject to proxied ips, and that's no use for localhost detection
141
- return ip && (ip === '::1' || ip.endsWith('127.0.0.1'));
142
- }
143
- exports.isLocalHost = isLocalHost;
144
- function same(a, b) {
145
- try {
146
- assert_1.default.deepStrictEqual(a, b);
147
- return true;
148
- }
149
- catch (_a) {
150
- return false;
151
- }
152
- }
153
- exports.same = same;
154
- function tryJson(s) {
155
- try {
156
- return s && JSON.parse(s);
157
- }
158
- catch (_a) { }
159
- }
160
- exports.tryJson = tryJson;
package/src/pbkdf2.js DELETED
@@ -1,74 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.pbkdf2Verify = exports.pbkdf2 = void 0;
4
- // @ts-nocheck
5
- const node_crypto_1 = require("node:crypto");
6
- // FROM https://gist.github.com/chrisveness/770ee96945ec12ac84f134bf538d89fb
7
- /**
8
- * Returns PBKDF2 derived key from supplied password.
9
- *
10
- * Stored key can subsequently be used to verify that a password matches the original password used
11
- * to derive the key, using pbkdf2Verify().
12
- *
13
- * @param {String} password - Password to be hashed using key derivation function.
14
- * @param {Number} [iterations=1e6] - Number of iterations of HMAC function to apply.
15
- * @returns {String} Derived key as base64 string.
16
- *
17
- * @example
18
- * const key = await pbkdf2('pāşšŵōřđ'); // eg 'djAxBRKXWNWPyXgpKWHld8SWJA9CQFmLyMbNet7Rle5RLKJAkBCllLfM6tPFa7bAis0lSTiB'
19
- */
20
- async function pbkdf2(password, iterations = 1e6) {
21
- const pwUtf8 = new TextEncoder().encode(password); // encode pw as UTF-8
22
- const pwKey = await node_crypto_1.webcrypto.subtle.importKey('raw', pwUtf8, 'PBKDF2', false, ['deriveBits']); // create pw key
23
- const saltUint8 = node_crypto_1.webcrypto.getRandomValues(new Uint8Array(16)); // get random salt
24
- const params = { name: 'PBKDF2', hash: 'SHA-256', salt: saltUint8, iterations: iterations }; // pbkdf2 params
25
- const keyBuffer = await node_crypto_1.webcrypto.subtle.deriveBits(params, pwKey, 256); // derive key
26
- const keyArray = Array.from(new Uint8Array(keyBuffer)); // key as byte array
27
- const saltArray = Array.from(new Uint8Array(saltUint8)); // salt as byte array
28
- const iterHex = ('000000' + iterations.toString(16)).slice(-6); // iter’n count as hex
29
- const iterArray = iterHex.match(/.{2}/g).map(byte => parseInt(byte, 16)); // iter’ns as byte array
30
- const compositeArray = [].concat(saltArray, iterArray, keyArray); // combined array
31
- const compositeStr = compositeArray.map(byte => String.fromCharCode(byte)).join(''); // combined as string
32
- // encode as base64
33
- return btoa('v01' + compositeStr); // return composite key
34
- }
35
- exports.pbkdf2 = pbkdf2;
36
- /**
37
- * Verifies whether the supplied password matches the password previously used to generate the key.
38
- *
39
- * @param {String} key - Key previously generated with pbkdf2().
40
- * @param {String} password - Password to be matched against previously derived key.
41
- * @returns {boolean} Whether password matches key.
42
- *
43
- * @example
44
- * const match = await pbkdf2Verify(key, 'pāşšŵōřđ'); // true
45
- */
46
- async function pbkdf2Verify(key, password) {
47
- let compositeStr = null; // composite key is salt, iteration count, and derived key
48
- try {
49
- compositeStr = atob(key);
50
- }
51
- catch (e) {
52
- throw new Error('Invalid key');
53
- } // decode from base64
54
- const version = compositeStr.slice(0, 3); // 3 bytes
55
- const saltStr = compositeStr.slice(3, 19); // 16 bytes (128 bits)
56
- const iterStr = compositeStr.slice(19, 22); // 3 bytes
57
- const keyStr = compositeStr.slice(22, 54); // 32 bytes (256 bits)
58
- if (version !== 'v01')
59
- throw new Error('Invalid key');
60
- // -- recover salt & iterations from stored (composite) key
61
- const saltUint8 = new Uint8Array(saltStr.match(/./g).map(ch => ch.charCodeAt(0))); // salt as Uint8Array
62
- // note: cannot use TextEncoder().encode(saltStr) as it generates UTF-8
63
- const iterHex = iterStr.match(/./g).map(ch => ch.charCodeAt(0).toString(16)).join(''); // iter’n count as hex
64
- const iterations = parseInt(iterHex, 16); // iter’ns
65
- // -- generate new key from stored salt & iterations and supplied password
66
- const pwUtf8 = new TextEncoder().encode(password); // encode pw as UTF-8
67
- const pwKey = await node_crypto_1.webcrypto.subtle.importKey('raw', pwUtf8, 'PBKDF2', false, ['deriveBits']); // create pw key
68
- const params = { name: 'PBKDF2', hash: 'SHA-256', salt: saltUint8, iterations: iterations }; // pbkdf params
69
- const keyBuffer = await node_crypto_1.webcrypto.subtle.deriveBits(params, pwKey, 256); // derive key
70
- const keyArray = Array.from(new Uint8Array(keyBuffer)); // key as byte array
71
- const keyStrNew = keyArray.map(byte => String.fromCharCode(byte)).join(''); // key as string
72
- return keyStrNew === keyStr; // test if newly generated key matches stored key
73
- }
74
- exports.pbkdf2Verify = pbkdf2Verify;