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
@@ -1,59 +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
- const api_helpers_1 = require("./api.helpers");
8
- const apiMiddleware_1 = require("./apiMiddleware");
9
- const perm_1 = require("./perm");
10
- const lodash_1 = __importDefault(require("lodash"));
11
- const const_1 = require("./const");
12
- function prepareAccount(ac) {
13
- return ac && {
14
- ...lodash_1.default.omit(ac, ['password', 'hashed_password', 'srp']),
15
- username: ac.username,
16
- hasPassword: (0, perm_1.accountHasPassword)(ac),
17
- adminActualAccess: (0, perm_1.accountCanLoginAdmin)(ac),
18
- };
19
- }
20
- const apis = {
21
- get_usernames() {
22
- return { list: Object.keys((0, perm_1.getAccounts)()) };
23
- },
24
- get_account({ username }, ctx) {
25
- return prepareAccount((0, perm_1.getAccount)(username || (0, perm_1.getCurrentUsername)(ctx)))
26
- || new apiMiddleware_1.ApiError(404);
27
- },
28
- get_accounts() {
29
- return { list: Object.values((0, perm_1.getAccounts)()).map(prepareAccount) };
30
- },
31
- get_admins() {
32
- return { list: Object.values((0, perm_1.getAccounts)()).map(prepareAccount).filter(ac => ac === null || ac === void 0 ? void 0 : ac.adminActualAccess).map(ac => ac.username) };
33
- },
34
- set_account({ username, changes }) {
35
- const { admin } = changes;
36
- if (admin === null)
37
- changes.admin = undefined;
38
- else if (admin !== undefined && typeof admin !== 'boolean')
39
- return new apiMiddleware_1.ApiError(400, "invalid admin");
40
- return (0, perm_1.setAccount)(username, changes) ? {} : new apiMiddleware_1.ApiError(400);
41
- },
42
- add_account({ username, ...rest }) {
43
- if ((0, perm_1.getAccount)(username))
44
- return new apiMiddleware_1.ApiError(const_1.FORBIDDEN);
45
- if (!(0, perm_1.addAccount)(username, rest))
46
- return new apiMiddleware_1.ApiError(400);
47
- return {};
48
- },
49
- del_account({ username }) {
50
- return (0, perm_1.delAccount)(username) ? {} : new apiMiddleware_1.ApiError(400);
51
- },
52
- async change_password_others({ username, newPassword }) {
53
- return (0, api_helpers_1.changePasswordHelper)((0, perm_1.getAccount)(username), newPassword);
54
- },
55
- async change_srp_others({ username, salt, verifier }) {
56
- return (0, api_helpers_1.changeSrpHelper)((0, perm_1.getAccount)(username), salt, verifier);
57
- }
58
- };
59
- exports.default = apis;
package/src/api.auth.js DELETED
@@ -1,130 +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
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.change_srp = exports.change_password = exports.refresh_session = exports.logout = exports.loginSrp2 = exports.srpStep1 = exports.loginSrp1 = exports.login = void 0;
5
- const perm_1 = require("./perm");
6
- const crypt_1 = require("./crypt");
7
- const apiMiddleware_1 = require("./apiMiddleware");
8
- const tssrp6a_1 = require("tssrp6a");
9
- const const_1 = require("./const");
10
- const misc_1 = require("./misc");
11
- const api_helpers_1 = require("./api.helpers");
12
- const adminApis_1 = require("./adminApis");
13
- const middlewares_1 = require("./middlewares");
14
- const srp6aNimbusRoutines = new tssrp6a_1.SRPRoutines(new tssrp6a_1.SRPParameters());
15
- const ongoingLogins = {}; // store data that doesn't fit session object
16
- // centralized log-in state
17
- async function loggedIn(ctx, username) {
18
- const s = ctx.session;
19
- if (!s)
20
- return ctx.throw(500, 'session');
21
- if (username === false) {
22
- delete s.username;
23
- ctx.cookies.set('csrf', '');
24
- return;
25
- }
26
- s.username = username;
27
- await (0, middlewares_1.prepareState)(ctx, async () => { }); // updating the state is necessary to send complete session data so that frontend shows admin button
28
- delete s.login;
29
- ctx.cookies.set('csrf', (0, misc_1.randomId)(), { signed: false, httpOnly: false });
30
- }
31
- function makeExp() {
32
- return { exp: new Date(Date.now() + const_1.SESSION_DURATION) };
33
- }
34
- const login = async ({ username, password }, ctx) => {
35
- if (!username || !password) // some validation
36
- return new apiMiddleware_1.ApiError(400);
37
- username = username.toLocaleLowerCase(); // normalize username, to be case-insensitive
38
- const acc = (0, perm_1.getAccount)(username);
39
- if (!acc)
40
- return new apiMiddleware_1.ApiError(const_1.UNAUTHORIZED);
41
- if (!acc.hashed_password)
42
- return new apiMiddleware_1.ApiError(406);
43
- if (!await (0, crypt_1.verifyPassword)(acc.hashed_password, password))
44
- return new apiMiddleware_1.ApiError(const_1.UNAUTHORIZED);
45
- if (!ctx.session)
46
- return new apiMiddleware_1.ApiError(500);
47
- await loggedIn(ctx, username);
48
- return { ...makeExp(), redirect: acc.redirect };
49
- };
50
- exports.login = login;
51
- const loginSrp1 = async ({ username }, ctx) => {
52
- if (!username)
53
- return new apiMiddleware_1.ApiError(400);
54
- username = username.toLocaleLowerCase();
55
- const account = (0, perm_1.getAccount)(username);
56
- if (!ctx.session)
57
- return new apiMiddleware_1.ApiError(500);
58
- if (!account) // TODO simulate fake account to prevent knowing valid usernames
59
- return new apiMiddleware_1.ApiError(const_1.UNAUTHORIZED);
60
- try {
61
- const { step1, ...rest } = await srpStep1(account);
62
- const sid = Math.random();
63
- ongoingLogins[sid] = step1;
64
- setTimeout(() => delete ongoingLogins[sid], 60000);
65
- ctx.session.login = { username, sid };
66
- return rest;
67
- }
68
- catch (code) {
69
- return new apiMiddleware_1.ApiError(code);
70
- }
71
- };
72
- exports.loginSrp1 = loginSrp1;
73
- async function srpStep1(account) {
74
- if (!account.srp)
75
- throw 406; // unacceptable
76
- const [salt, verifier] = account.srp.split('|');
77
- const srpSession = new tssrp6a_1.SRPServerSession(srp6aNimbusRoutines);
78
- const step1 = await srpSession.step1(account.username, BigInt(salt), BigInt(verifier));
79
- return { step1, salt, pubKey: String(step1.B) }; // cast to string cause bigint can't be jsonized
80
- }
81
- exports.srpStep1 = srpStep1;
82
- const loginSrp2 = async ({ pubKey, proof }, ctx) => {
83
- var _a;
84
- if (!ctx.session)
85
- return new apiMiddleware_1.ApiError(500);
86
- if (!ctx.session.login)
87
- return new apiMiddleware_1.ApiError(409);
88
- const { username, sid } = ctx.session.login;
89
- const step1 = ongoingLogins[sid];
90
- try {
91
- const M2 = await step1.step2(BigInt(pubKey), BigInt(proof));
92
- await loggedIn(ctx, username);
93
- return {
94
- proof: String(M2),
95
- redirect: (_a = ctx.state.account) === null || _a === void 0 ? void 0 : _a.redirect,
96
- ...await (0, exports.refresh_session)({}, ctx)
97
- };
98
- }
99
- catch (e) {
100
- return new apiMiddleware_1.ApiError(const_1.UNAUTHORIZED, String(e));
101
- }
102
- finally {
103
- delete ongoingLogins[sid];
104
- }
105
- };
106
- exports.loginSrp2 = loginSrp2;
107
- const logout = async ({}, ctx) => {
108
- if (!ctx.session)
109
- return new apiMiddleware_1.ApiError(500);
110
- loggedIn(ctx, false);
111
- // 401 is a convenient code for OK: the browser clears a possible http authentication (hopefully), and Admin automatically triggers login dialog
112
- return new apiMiddleware_1.ApiError(401);
113
- };
114
- exports.logout = logout;
115
- const refresh_session = async ({}, ctx) => {
116
- return !ctx.session ? new apiMiddleware_1.ApiError(500) : {
117
- username: (0, perm_1.getCurrentUsername)(ctx),
118
- adminUrl: (0, adminApis_1.ctxAdminAccess)(ctx) ? const_1.ADMIN_URI : undefined,
119
- ...makeExp(),
120
- };
121
- };
122
- exports.refresh_session = refresh_session;
123
- const change_password = async ({ newPassword }, ctx) => {
124
- return (0, api_helpers_1.changePasswordHelper)(ctx.state.account, newPassword);
125
- };
126
- exports.change_password = change_password;
127
- const change_srp = async ({ salt, verifier }, ctx) => {
128
- return (0, api_helpers_1.changeSrpHelper)(ctx.state.account, salt, verifier);
129
- };
130
- exports.change_srp = change_srp;
@@ -1,103 +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.file_list = void 0;
8
- const vfs_1 = require("./vfs");
9
- const apiMiddleware_1 = require("./apiMiddleware");
10
- const promises_1 = require("fs/promises");
11
- const plugins_1 = require("./plugins");
12
- const misc_1 = require("./misc");
13
- const lodash_1 = __importDefault(require("lodash"));
14
- const file_list = async ({ path, offset, limit, search, omit, sse }, ctx) => {
15
- let node = await (0, vfs_1.urlToNode)(path || '/', ctx);
16
- const list = new apiMiddleware_1.SendListReadable();
17
- if (!node)
18
- return fail(404);
19
- if (!(0, vfs_1.hasPermission)(node, 'can_read', ctx))
20
- return fail((0, vfs_1.cantReadStatusCode)(node));
21
- if ((0, misc_1.dirTraversal)(search))
22
- return fail(418);
23
- if (node.default)
24
- return (sse ? list.custom : lodash_1.default.identity)({ redirect: path }); // sse will wrap the object in a 'custom' message, otherwise we plainly return the object
25
- if (!await (0, vfs_1.nodeIsDirectory)(node))
26
- return fail(405); // method not allowed on target
27
- offset = Number(offset);
28
- limit = Number(limit);
29
- const filter = (0, misc_1.pattern2filter)(search);
30
- const walker = (0, vfs_1.walkNode)(node, ctx, search ? Infinity : 0);
31
- const onDirEntryHandlers = (0, plugins_1.mapPlugins)(plug => plug.onDirEntry);
32
- if (!sse)
33
- return { list: await (0, misc_1.asyncGeneratorToArray)(produceEntries()) };
34
- setTimeout(async () => {
35
- for await (const entry of produceEntries())
36
- list.add(entry);
37
- list.close();
38
- });
39
- return list;
40
- function fail(code) {
41
- if (!sse)
42
- return new apiMiddleware_1.ApiError(code);
43
- list.error(code);
44
- list.close();
45
- return list;
46
- }
47
- async function* produceEntries() {
48
- for await (const sub of walker) {
49
- if (ctx.aborted)
50
- break;
51
- if (!filter((0, vfs_1.getNodeName)(sub)))
52
- continue;
53
- const entry = await nodeToDirEntry(sub);
54
- if (!entry)
55
- continue;
56
- const cbParams = { entry, ctx, listPath: path, node: sub };
57
- try {
58
- if (onDirEntryHandlers.some(cb => cb(cbParams) === false))
59
- continue;
60
- }
61
- catch (e) {
62
- console.log("a plugin with onDirEntry is causing problems:", e);
63
- }
64
- if (offset) {
65
- --offset;
66
- continue;
67
- }
68
- if (omit) {
69
- if (omit !== 'c')
70
- ctx.throw(400, 'omit');
71
- if (!entry.m)
72
- entry.m = entry.c;
73
- delete entry.c;
74
- }
75
- yield entry;
76
- if (limit && !--limit)
77
- break;
78
- }
79
- }
80
- };
81
- exports.file_list = file_list;
82
- async function nodeToDirEntry(node) {
83
- let { source, default: def } = node;
84
- const name = (0, vfs_1.getNodeName)(node);
85
- if (!source)
86
- return name ? { n: name + '/' } : null;
87
- if (def)
88
- return { n: name };
89
- try {
90
- const st = await (0, promises_1.stat)(source);
91
- const folder = st.isDirectory();
92
- const { ctime, mtime } = st;
93
- return {
94
- n: name + (folder ? '/' : ''),
95
- c: ctime,
96
- m: Math.abs(+mtime - +ctime) < 1000 ? undefined : mtime,
97
- s: folder ? undefined : st.size,
98
- };
99
- }
100
- catch (_a) {
101
- return null;
102
- }
103
- }
@@ -1,32 +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
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.changeSrpHelper = exports.changePasswordHelper = void 0;
5
- const perm_1 = require("./perm");
6
- const apiMiddleware_1 = require("./apiMiddleware");
7
- const const_1 = require("./const");
8
- async function changePasswordHelper(account, newPassword) {
9
- if (!newPassword) // clear text version
10
- return Error('missing parameters');
11
- if (!account)
12
- return new apiMiddleware_1.ApiError(const_1.UNAUTHORIZED);
13
- await (0, perm_1.updateAccount)(account, account => {
14
- account.password = newPassword;
15
- });
16
- return {};
17
- }
18
- exports.changePasswordHelper = changePasswordHelper;
19
- async function changeSrpHelper(account, salt, verifier) {
20
- if (perm_1.allowClearTextLogin.get())
21
- return new apiMiddleware_1.ApiError(406);
22
- if (!salt || !verifier)
23
- return Error('missing parameters');
24
- if (!account)
25
- return new apiMiddleware_1.ApiError(const_1.UNAUTHORIZED);
26
- await (0, perm_1.updateAccount)(account, account => {
27
- (0, perm_1.saveSrpInfo)(account, salt, verifier);
28
- delete account.hashed_password; // remove leftovers
29
- });
30
- return {};
31
- }
32
- exports.changeSrpHelper = changeSrpHelper;
@@ -1,102 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const lodash_1 = __importDefault(require("lodash"));
7
- const connections_1 = require("./connections");
8
- const misc_1 = require("./misc");
9
- const apiMiddleware_1 = require("./apiMiddleware");
10
- const throttler_1 = require("./throttler");
11
- const perm_1 = require("./perm");
12
- const apis = {
13
- async disconnect({ ip, port, wait }) {
14
- const match = lodash_1.default.matches({ ip, port });
15
- const c = (0, connections_1.getConnections)().find(c => match(getConnAddress(c)));
16
- const waiter = (0, misc_1.pendingPromise)();
17
- c === null || c === void 0 ? void 0 : c.socket.end(waiter.resolve);
18
- if (wait)
19
- await waiter;
20
- return { result: Boolean(c) };
21
- },
22
- get_connections({}, ctx) {
23
- const list = new apiMiddleware_1.SendListReadable({ addAtStart: (0, connections_1.getConnections)().map(c => serializeConnection(c)) });
24
- const throttledUpdate = lodash_1.default.throttle(update, 1000 / 20); // try to avoid clogging with updates
25
- const state = Symbol('state'); // undefined=added, Timeout=add-pending, false=removed
26
- return list.events(ctx, {
27
- connection(conn) {
28
- conn[state] = setTimeout(() => add(conn), 100);
29
- },
30
- connectionClosed(conn) {
31
- if (cancel(conn))
32
- return;
33
- list.remove(serializeConnection(conn, true));
34
- conn[state] = false;
35
- },
36
- connectionUpdated(conn, change) {
37
- if (!change.ctx)
38
- return throttledUpdate(conn, change);
39
- Object.assign(change, fromCtx(change.ctx));
40
- change.ctx = undefined;
41
- if (!add(conn))
42
- throttledUpdate(conn, change);
43
- },
44
- });
45
- function add(conn) {
46
- if (!cancel(conn))
47
- return;
48
- list.add(serializeConnection(conn));
49
- return true;
50
- }
51
- function cancel(conn) {
52
- if (!conn[state])
53
- return;
54
- clearTimeout(conn[state]);
55
- conn[state] = undefined;
56
- return true;
57
- }
58
- function update(conn, change) {
59
- if (conn[state] === false)
60
- return;
61
- list.update(serializeConnection(conn, true), change);
62
- }
63
- function serializeConnection(conn, minimal) {
64
- var _a;
65
- const { socket, started, secure } = conn;
66
- return Object.assign(getConnAddress(conn), !minimal && {
67
- v: (((_a = socket.remoteFamily) === null || _a === void 0 ? void 0 : _a.endsWith('6')) ? 6 : 4),
68
- got: socket.bytesRead,
69
- sent: socket.bytesWritten,
70
- started,
71
- secure: (secure || undefined),
72
- ...fromCtx(conn.ctx),
73
- });
74
- }
75
- function fromCtx(ctx) {
76
- return ctx && {
77
- user: (0, perm_1.getCurrentUsername)(ctx),
78
- archive: ctx.state.archive,
79
- path: (ctx.fileSource || ctx.state.archive) && ctx.path // only for downloading files
80
- };
81
- }
82
- },
83
- async *get_connection_stats() {
84
- while (1) {
85
- yield {
86
- outSpeed: throttler_1.totalOutSpeed,
87
- inSpeed: throttler_1.totalInSpeed,
88
- got: throttler_1.totalGot,
89
- sent: throttler_1.totalSent,
90
- connections: (0, connections_1.getConnections)().length
91
- };
92
- await (0, misc_1.wait)(1000);
93
- }
94
- },
95
- };
96
- exports.default = apis;
97
- function getConnAddress(conn) {
98
- return {
99
- ip: conn.ip,
100
- port: conn.socket.remotePort,
101
- };
102
- }
@@ -1,127 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const plugins_1 = require("./plugins");
7
- const lodash_1 = __importDefault(require("lodash"));
8
- const assert_1 = __importDefault(require("assert"));
9
- const misc_1 = require("./misc");
10
- const apiMiddleware_1 = require("./apiMiddleware");
11
- const events_1 = __importDefault(require("./events"));
12
- const promises_1 = require("fs/promises");
13
- const github_1 = require("./github");
14
- const apis = {
15
- get_plugins({}, ctx) {
16
- const list = new apiMiddleware_1.SendListReadable({ addAtStart: [...(0, plugins_1.mapPlugins)(serialize), ...(0, plugins_1.getAvailablePlugins)()] });
17
- return list.events(ctx, {
18
- pluginInstalled: p => list.add(serialize(p)),
19
- 'pluginStarted pluginStopped pluginUpdated': p => {
20
- const { id, ...rest } = serialize(p);
21
- list.update({ id }, rest);
22
- },
23
- pluginUninstalled: id => list.remove({ id }),
24
- });
25
- function serialize(p) {
26
- const o = 'getData' in p ? Object.assign(lodash_1.default.pick(p, ['id', 'started']), p.getData())
27
- : { ...p }; // _.defaults mutates object, and we don't want that
28
- return lodash_1.default.defaults(o, { started: null, badApi: null }); // nulls should be used to be sure to overwrite previous values,
29
- }
30
- },
31
- async get_plugin_updates() {
32
- const list = new apiMiddleware_1.SendListReadable();
33
- setTimeout(async () => {
34
- for (const [folder, repo] of Object.entries((0, github_1.getFolder2repo)()))
35
- try {
36
- if (!repo)
37
- continue;
38
- const online = await (0, github_1.readOnlinePlugin)(await (0, github_1.getRepoInfo)(repo));
39
- if (!online.apiRequired || online.badApi)
40
- continue;
41
- const disk = (0, plugins_1.getPluginInfo)(folder);
42
- if (online.version > disk.version)
43
- list.add(online);
44
- }
45
- catch (err) {
46
- list.error(err.code || err.message);
47
- }
48
- list.close();
49
- });
50
- return list;
51
- },
52
- async set_plugin({ id, enabled, config }) {
53
- (0, assert_1.default)(id, 'id');
54
- if (enabled !== undefined)
55
- (0, plugins_1.enablePlugin)(id, enabled);
56
- if (config)
57
- (0, plugins_1.setPluginConfig)(id, config);
58
- return {};
59
- },
60
- async get_plugin({ id }) {
61
- return {
62
- enabled: plugins_1.enablePlugins.get().includes(id),
63
- config: {
64
- ...(0, misc_1.objSameKeys)((0, plugins_1.getPluginConfigFields)(id) || {}, v => v === null || v === void 0 ? void 0 : v.defaultValue),
65
- ...plugins_1.pluginsConfig.get()[id]
66
- }
67
- };
68
- },
69
- search_online_plugins({ text }, ctx) {
70
- return new apiMiddleware_1.SendListReadable({
71
- async doAtStart(list) {
72
- try {
73
- const folder2repo = (0, github_1.getFolder2repo)();
74
- for await (const pl of (0, github_1.searchPlugins)(text)) {
75
- const repo = pl.id;
76
- const folder = lodash_1.default.findKey(folder2repo, x => x === repo);
77
- const installed = folder && (0, plugins_1.getPluginInfo)(folder);
78
- Object.assign(pl, {
79
- installed: lodash_1.default.includes(folder2repo, repo),
80
- update: installed && installed.version < pl.version,
81
- });
82
- list.add(pl);
83
- // watch for events about this plugin, until this request is closed
84
- ctx.req.on('close', (0, misc_1.onOff)(events_1.default, {
85
- pluginInstalled: p => {
86
- if (p.repo === repo)
87
- list.update({ id: repo }, { installed: true });
88
- },
89
- pluginUninstalled: folder => {
90
- if (repo === (0, github_1.getFolder2repo)()[folder])
91
- list.update({ id: repo }, { installed: false });
92
- },
93
- pluginUpdated: p => {
94
- if (p.repo === repo)
95
- list.update({ id: repo }, { update: p.version < pl.version });
96
- },
97
- ['pluginDownload_' + repo](status) {
98
- list.update({ id: repo }, { downloading: status !== null && status !== void 0 ? status : null });
99
- }
100
- }));
101
- }
102
- }
103
- catch (err) {
104
- list.error(err.code || err.message);
105
- }
106
- list.ready();
107
- }
108
- });
109
- },
110
- async download_plugin(pl) {
111
- const res = await (0, github_1.downloadPlugin)(pl.id, pl.branch);
112
- return typeof res === 'string' ? (0, plugins_1.getPluginInfo)(res) : res;
113
- },
114
- async update_plugin(pl) {
115
- await (0, github_1.downloadPlugin)(pl.id, pl.branch, true);
116
- return {};
117
- },
118
- async uninstall_plugin({ id }) {
119
- while ((0, plugins_1.isPluginRunning)(id)) {
120
- (0, plugins_1.enablePlugin)(id, false);
121
- await (0, misc_1.wait)(500);
122
- }
123
- await (0, promises_1.rm)(plugins_1.PATH + '/' + id, { recursive: true, force: true });
124
- return {};
125
- }
126
- };
127
- exports.default = apis;