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.
- package/admin/.DS_Store +0 -0
- package/admin/.eslintrc +8 -0
- package/admin/.gitignore +23 -0
- package/admin/index.html +1 -3
- package/admin/package.json +67 -0
- package/admin/{logo.svg → public/logo.svg} +0 -0
- package/admin/src/AccountForm.ts +92 -0
- package/admin/src/AccountsPage.ts +143 -0
- package/admin/src/App.ts +83 -0
- package/admin/src/ArrayField.ts +84 -0
- package/admin/src/ConfigPage.ts +279 -0
- package/admin/src/FileField.ts +52 -0
- package/admin/src/FileForm.ts +148 -0
- package/admin/src/FilePicker.ts +166 -0
- package/admin/src/HomePage.ts +96 -0
- package/admin/src/InstalledPlugins.ts +158 -0
- package/admin/src/LoginRequired.ts +75 -0
- package/admin/src/LogoutPage.ts +27 -0
- package/admin/src/LogsPage.ts +75 -0
- package/admin/src/MainMenu.ts +74 -0
- package/admin/src/MenuButton.ts +38 -0
- package/admin/src/MonitorPage.ts +200 -0
- package/admin/src/OnlinePlugins.ts +101 -0
- package/admin/src/PermField.ts +80 -0
- package/admin/src/PluginsPage.ts +27 -0
- package/admin/src/VfsMenuBar.ts +58 -0
- package/admin/src/VfsPage.ts +124 -0
- package/admin/src/VfsTree.ts +95 -0
- package/admin/src/addFiles.ts +59 -0
- package/admin/src/api.ts +246 -0
- package/admin/src/dialog.ts +203 -0
- package/admin/src/index.css +21 -0
- package/admin/src/index.ts +10 -0
- package/admin/src/md.ts +31 -0
- package/admin/src/misc.ts +141 -0
- package/admin/src/react-app-env.d.ts +1 -0
- package/admin/src/reportWebVitals.ts +15 -0
- package/admin/src/setupTests.ts +5 -0
- package/admin/src/state.ts +40 -0
- package/admin/src/theme.ts +37 -0
- package/admin/tsconfig.json +26 -0
- package/admin/vite.config.ts +32 -0
- package/frontend/.DS_Store +0 -0
- package/frontend/.eslintrc +8 -0
- package/frontend/.gitignore +23 -0
- package/frontend/index.html +1 -3
- package/frontend/package.json +51 -0
- package/frontend/{fontello.css → public/fontello.css} +0 -0
- package/frontend/{fontello.woff2 → public/fontello.woff2} +0 -0
- package/frontend/src/App.ts +25 -0
- package/frontend/src/Breadcrumbs.ts +43 -0
- package/frontend/src/BrowseFiles.ts +141 -0
- package/frontend/src/Head.ts +45 -0
- package/frontend/src/UserPanel.ts +52 -0
- package/frontend/src/api.ts +78 -0
- package/frontend/src/components.ts +54 -0
- package/frontend/src/dialog.css +76 -0
- package/frontend/src/dialog.ts +105 -0
- package/frontend/src/icons.ts +46 -0
- package/frontend/src/index.scss +307 -0
- package/frontend/src/index.ts +10 -0
- package/frontend/src/login.ts +50 -0
- package/frontend/src/menu.ts +188 -0
- package/frontend/src/misc.ts +54 -0
- package/frontend/src/options.ts +52 -0
- package/frontend/src/react-app-env.d.ts +1 -0
- package/frontend/src/reportWebVitals.ts +15 -0
- package/frontend/src/setupTests.ts +5 -0
- package/frontend/src/state.ts +82 -0
- package/frontend/src/useAuthorized.ts +17 -0
- package/frontend/src/useFetchList.ts +144 -0
- package/frontend/src/useTheme.ts +23 -0
- package/frontend/tsconfig.json +26 -0
- package/frontend/vite.config.ts +21 -0
- package/package.json +2 -1
- package/plugins/vhosting/plugin.js +1 -1
- package/src/QuickZipStream.ts +279 -0
- package/src/ThrottledStream.ts +98 -0
- package/src/adminApis.ts +161 -0
- package/src/api.accounts.ts +78 -0
- package/src/api.auth.ts +131 -0
- package/src/api.file_list.ts +102 -0
- package/src/api.helpers.ts +30 -0
- package/src/api.monitor.ts +106 -0
- package/src/api.plugins.ts +139 -0
- package/src/api.vfs.ts +182 -0
- package/src/apiMiddleware.ts +124 -0
- package/src/block.ts +35 -0
- package/src/commands.ts +122 -0
- package/src/config.ts +166 -0
- package/src/connections.ts +60 -0
- package/src/const.ts +57 -0
- package/src/crypt.ts +16 -0
- package/src/debounceAsync.ts +51 -0
- package/src/events.ts +6 -0
- package/src/frontEndApis.ts +17 -0
- package/src/github.ts +102 -0
- package/src/index.ts +53 -0
- package/src/listen.ts +220 -0
- package/src/log.ts +128 -0
- package/src/middlewares.ts +176 -0
- package/src/misc.ts +149 -0
- package/src/pbkdf2.ts +83 -0
- package/src/perm.ts +194 -0
- package/src/plugins.ts +342 -0
- package/src/serveFile.ts +104 -0
- package/src/serveGuiFiles.ts +95 -0
- package/src/sse.ts +29 -0
- package/src/throttler.ts +106 -0
- package/src/update.ts +67 -0
- package/src/util-files.ts +137 -0
- package/src/util-generators.ts +29 -0
- package/src/util-http.ts +29 -0
- package/src/vfs.ts +258 -0
- package/src/watchLoad.ts +75 -0
- package/src/zip.ts +69 -0
- package/admin/assets/index.0f549e00.js +0 -281
- package/admin/assets/index.dcc78777.css +0 -1
- package/admin/assets/sha512.ea1121b3.js +0 -8
- package/frontend/assets/index.1151988f.js +0 -85
- package/frontend/assets/index.93366732.css +0 -1
- package/frontend/assets/sha512.bb881250.js +0 -8
- package/src/QuickZipStream.js +0 -285
- package/src/ThrottledStream.js +0 -93
- package/src/adminApis.js +0 -169
- package/src/api.accounts.js +0 -59
- package/src/api.auth.js +0 -130
- package/src/api.file_list.js +0 -103
- package/src/api.helpers.js +0 -32
- package/src/api.monitor.js +0 -102
- package/src/api.plugins.js +0 -127
- package/src/api.vfs.js +0 -164
- package/src/apiMiddleware.js +0 -136
- package/src/block.js +0 -33
- package/src/commands.js +0 -124
- package/src/config.js +0 -168
- package/src/connections.js +0 -57
- package/src/const.js +0 -83
- package/src/crypt.js +0 -21
- package/src/debounceAsync.js +0 -48
- package/src/events.js +0 -9
- package/src/frontEndApis.js +0 -38
- package/src/github.js +0 -102
- package/src/index.js +0 -55
- package/src/listen.js +0 -235
- package/src/log.js +0 -137
- package/src/middlewares.js +0 -154
- package/src/misc.js +0 -160
- package/src/pbkdf2.js +0 -74
- package/src/perm.js +0 -176
- package/src/plugins.js +0 -343
- package/src/serveFile.js +0 -104
- package/src/serveGuiFiles.js +0 -113
- package/src/sse.js +0 -29
- package/src/throttler.js +0 -91
- package/src/update.js +0 -69
- package/src/util-files.js +0 -148
- package/src/util-generators.js +0 -30
- package/src/util-http.js +0 -30
- package/src/vfs.js +0 -227
- package/src/watchLoad.js +0 -73
- package/src/zip.js +0 -69
package/src/api.accounts.js
DELETED
|
@@ -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;
|
package/src/api.file_list.js
DELETED
|
@@ -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
|
-
}
|
package/src/api.helpers.js
DELETED
|
@@ -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;
|
package/src/api.monitor.js
DELETED
|
@@ -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
|
-
}
|
package/src/api.plugins.js
DELETED
|
@@ -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;
|