hfs 0.29.1 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/admin/assets/index-57af5a8c.js +414 -0
- package/admin/assets/index-6f45486d.css +1 -0
- package/{frontend/assets/sha512-2c2fa926.js → admin/assets/sha512-15452202.js} +1 -1
- package/admin/{logo.svg → cup.svg} +0 -0
- package/admin/hfs-logo-icon.svg +46 -0
- package/admin/hfs-logo.svg +43 -0
- package/admin/index.html +3 -3
- package/frontend/assets/index-35d3e75f.css +1 -0
- package/frontend/assets/index-b557b421.js +85 -0
- package/{admin/assets/sha512-3273321f.js → frontend/assets/sha512-d95215fa.js} +1 -1
- package/frontend/index.html +2 -2
- package/package.json +2 -1
- package/src/adminApis.js +8 -2
- package/src/api.accounts.js +3 -1
- package/src/api.vfs.js +4 -2
- package/src/apiMiddleware.js +2 -2
- package/src/const.js +1 -1
- package/src/index.js +0 -2
- package/src/middlewares.js +13 -1
- package/src/watchLoad.js +13 -19
- package/admin/assets/index-cbb42a0e.js +0 -415
- package/admin/assets/index-f8049da8.css +0 -1
- package/frontend/assets/index-72e96bb2.js +0 -85
- package/frontend/assets/index-cbcc6ac5.css +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{c as SF}from"./index-
|
|
1
|
+
import{c as SF}from"./index-b557b421.js";function OF(iF,hF){for(var eF=0;eF<hF.length;eF++){const tF=hF[eF];if(typeof tF!="string"&&!Array.isArray(tF)){for(const w in tF)if(w!=="default"&&!(w in iF)){const lF=Object.getOwnPropertyDescriptor(tF,w);lF&&Object.defineProperty(iF,w,lF.get?lF:{enumerable:!0,get:()=>tF[w]})}}}return Object.freeze(Object.defineProperty(iF,Symbol.toStringTag,{value:"Module"}))}var EF={},UF={get exports(){return EF},set exports(iF){EF=iF}};/*
|
|
2
2
|
* [js-sha512]{@link https://github.com/emn178/js-sha512}
|
|
3
3
|
*
|
|
4
4
|
* @version 0.8.0
|
package/frontend/index.html
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
<link href="/fontello.css" rel="stylesheet" />
|
|
7
7
|
<script>SESSION = _HFS_SESSION_</script>
|
|
8
8
|
<title>File Server</title>
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
10
|
-
<link rel="stylesheet" href="/assets/index-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-b557b421.js"></script>
|
|
10
|
+
<link rel="stylesheet" href="/assets/index-35d3e75f.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
|
13
13
|
<div hidden>_HFS_PLUGINS_</div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hfs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.0",
|
|
4
4
|
"description": "HTTP File Server",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"file server",
|
|
@@ -96,6 +96,7 @@
|
|
|
96
96
|
"@types/unzipper": "^0.10.5",
|
|
97
97
|
"axios": "^0.24.0",
|
|
98
98
|
"axios-cookiejar-support": "^4.0.1",
|
|
99
|
+
"cross-env": "^7.0.3",
|
|
99
100
|
"koa-better-http-proxy": "^0.2.9",
|
|
100
101
|
"mocha": "^9.1.3",
|
|
101
102
|
"nm-prune": "^5.0.0",
|
package/src/adminApis.js
CHANGED
|
@@ -150,8 +150,14 @@ exports.adminApis = {
|
|
|
150
150
|
},
|
|
151
151
|
};
|
|
152
152
|
for (const [k, was] of Object.entries(exports.adminApis))
|
|
153
|
-
exports.adminApis[k] = (params, ctx) =>
|
|
154
|
-
|
|
153
|
+
exports.adminApis[k] = (params, ctx) => {
|
|
154
|
+
if (ctxAdminAccess(ctx))
|
|
155
|
+
return was(params, ctx);
|
|
156
|
+
const props = { any: (0, perm_1.anyAccountCanLoginAdmin)() };
|
|
157
|
+
return ctx.headers.accept === 'text/event-stream'
|
|
158
|
+
? new apiMiddleware_1.SendListReadable({ doAtStart: x => x.error(const_1.HTTP_UNAUTHORIZED, true, props) })
|
|
159
|
+
: new apiMiddleware_1.ApiError(const_1.HTTP_UNAUTHORIZED, props);
|
|
160
|
+
};
|
|
155
161
|
exports.localhostAdmin = (0, config_1.defineConfig)('localhost_admin', true);
|
|
156
162
|
function ctxAdminAccess(ctx) {
|
|
157
163
|
return !ctx.state.proxiedFor // we consider localhost_admin only if no proxy is detected
|
package/src/api.accounts.js
CHANGED
|
@@ -31,13 +31,15 @@ const apis = {
|
|
|
31
31
|
get_admins() {
|
|
32
32
|
return { list: lodash_1.default.filter(perm_1.accountsConfig.get(), perm_1.accountCanLoginAdmin).map(ac => ac.username) };
|
|
33
33
|
},
|
|
34
|
-
set_account({ username, changes }) {
|
|
34
|
+
set_account({ username, changes }, ctx) {
|
|
35
35
|
const { admin } = changes;
|
|
36
36
|
if (admin === null)
|
|
37
37
|
changes.admin = undefined;
|
|
38
38
|
else if (admin !== undefined && typeof admin !== 'boolean')
|
|
39
39
|
return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, "invalid admin");
|
|
40
40
|
const acc = (0, perm_1.setAccount)(username, changes);
|
|
41
|
+
if (changes.username && ctx.session)
|
|
42
|
+
ctx.session.username = changes.username;
|
|
41
43
|
return acc ? lodash_1.default.pick(acc, 'username') : new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST);
|
|
42
44
|
},
|
|
43
45
|
add_account({ username, ...rest }) {
|
package/src/api.vfs.js
CHANGED
|
@@ -84,13 +84,15 @@ const apis = {
|
|
|
84
84
|
errors: await Promise.all(uris.map(async (uri) => {
|
|
85
85
|
if (typeof uri !== 'string')
|
|
86
86
|
return const_1.HTTP_BAD_REQUEST;
|
|
87
|
+
if (uri === '/')
|
|
88
|
+
return const_1.HTTP_NOT_ACCEPTABLE;
|
|
87
89
|
const node = await urlToNodeOriginal(uri);
|
|
88
90
|
if (!node)
|
|
89
91
|
return const_1.HTTP_NOT_FOUND;
|
|
90
92
|
const parent = (0, path_1.dirname)(uri);
|
|
91
93
|
const parentNode = await urlToNodeOriginal(parent);
|
|
92
|
-
if (!parentNode)
|
|
93
|
-
return const_1.
|
|
94
|
+
if (!parentNode) // shouldn't happen
|
|
95
|
+
return const_1.HTTP_SERVER_ERROR;
|
|
94
96
|
const { children } = parentNode;
|
|
95
97
|
if (!children) // shouldn't happen
|
|
96
98
|
return const_1.HTTP_SERVER_ERROR;
|
package/src/apiMiddleware.js
CHANGED
|
@@ -102,8 +102,8 @@ class SendListReadable extends stream_1.Readable {
|
|
|
102
102
|
props(props) {
|
|
103
103
|
this._push({ props });
|
|
104
104
|
}
|
|
105
|
-
error(msg, close = false) {
|
|
106
|
-
this._push({ error: msg });
|
|
105
|
+
error(msg, close = false, props) {
|
|
106
|
+
this._push({ error: msg, ...props });
|
|
107
107
|
this.lastError = msg;
|
|
108
108
|
if (close)
|
|
109
109
|
this.close();
|
package/src/const.js
CHANGED
|
@@ -38,7 +38,7 @@ exports.DEV = process.env.DEV || exports.argv.dev ? 'DEV' : '';
|
|
|
38
38
|
exports.ORIGINAL_CWD = process.cwd();
|
|
39
39
|
exports.HFS_STARTED = new Date();
|
|
40
40
|
const PKG_PATH = (0, path_1.join)(__dirname, '..', 'package.json');
|
|
41
|
-
exports.BUILD_TIMESTAMP = "2023-
|
|
41
|
+
exports.BUILD_TIMESTAMP = "2023-02-04T16:32:19.926Z";
|
|
42
42
|
const pkg = JSON.parse(fs.readFileSync(PKG_PATH, 'utf8'));
|
|
43
43
|
exports.VERSION = pkg.version;
|
|
44
44
|
exports.DAY = 86400000;
|
package/src/index.js
CHANGED
|
@@ -23,7 +23,6 @@ const config_1 = require("./config");
|
|
|
23
23
|
const assert_1 = require("assert");
|
|
24
24
|
const lodash_1 = __importDefault(require("lodash"));
|
|
25
25
|
const misc_1 = require("./misc");
|
|
26
|
-
//import body from 'koa-better-body'
|
|
27
26
|
(0, assert_1.ok)(lodash_1.default.intersection(Object.keys(frontEndApis_1.frontEndApis), Object.keys(adminApis_1.adminApis)).length === 0); // they share same endpoints
|
|
28
27
|
const keys = ((_a = process.env.COOKIE_SIGN_KEYS) === null || _a === void 0 ? void 0 : _a.split(',')) || [(0, misc_1.randomId)(30)];
|
|
29
28
|
exports.app = new koa_1.default({ keys });
|
|
@@ -36,7 +35,6 @@ exports.app.use(middlewares_1.someSecurity)
|
|
|
36
35
|
.use(middlewares_1.gzipper)
|
|
37
36
|
.use((0, plugins_1.pluginsMiddleware)())
|
|
38
37
|
.use((0, koa_mount_1.default)(const_1.API_URI, (0, apiMiddleware_1.apiMiddleware)({ ...frontEndApis_1.frontEndApis, ...adminApis_1.adminApis })))
|
|
39
|
-
//.use(body({ multipart: false }))
|
|
40
38
|
.use(middlewares_1.serveGuiAndSharedFiles)
|
|
41
39
|
.on('error', errorHandler);
|
|
42
40
|
function errorHandler(err) {
|
package/src/middlewares.js
CHANGED
|
@@ -59,9 +59,21 @@ const sessions = (app) => (0, koa_session_1.default)({
|
|
|
59
59
|
exports.sessions = sessions;
|
|
60
60
|
const serveFrontendFiles = (0, serveGuiFiles_1.serveGuiFiles)(process.env.FRONTEND_PROXY, const_2.FRONTEND_URI);
|
|
61
61
|
const serveFrontendPrefixed = (0, koa_mount_1.default)(const_2.FRONTEND_URI.slice(0, -1), serveFrontendFiles);
|
|
62
|
-
const
|
|
62
|
+
const serveAdminFiles = (0, serveGuiFiles_1.serveGuiFiles)(process.env.ADMIN_PROXY, const_1.ADMIN_URI);
|
|
63
|
+
const serveAdminPrefixed = (0, koa_mount_1.default)(const_1.ADMIN_URI.slice(0, -1), serveAdminFiles);
|
|
63
64
|
const serveGuiAndSharedFiles = async (ctx, next) => {
|
|
64
65
|
const { path } = ctx;
|
|
66
|
+
// dynamic import on frontend|admin (used for non-https login) while developing (vite4) is not producing a relative path
|
|
67
|
+
if (const_1.DEV && path.startsWith('/node_modules/')) {
|
|
68
|
+
let { referer } = ctx.headers;
|
|
69
|
+
referer && (referer = new URL(referer).pathname);
|
|
70
|
+
if (referer) {
|
|
71
|
+
if (referer.startsWith(const_1.ADMIN_URI))
|
|
72
|
+
return serveAdminFiles(ctx, next);
|
|
73
|
+
if (referer.startsWith(const_2.FRONTEND_URI))
|
|
74
|
+
return serveFrontendFiles(ctx, next);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
65
77
|
if (ctx.body)
|
|
66
78
|
return next();
|
|
67
79
|
if (path.startsWith(const_2.FRONTEND_URI))
|
package/src/watchLoad.js
CHANGED
|
@@ -12,10 +12,10 @@ const misc_1 = require("./misc");
|
|
|
12
12
|
function watchLoad(path, parser, { failedOnFirstAttempt } = {}) {
|
|
13
13
|
let doing = false;
|
|
14
14
|
let watcher;
|
|
15
|
-
const debounced = (0, misc_1.debounceAsync)(load, 500, {
|
|
15
|
+
const debounced = (0, misc_1.debounceAsync)(load, 500, { maxWait: 1000 });
|
|
16
16
|
let retry;
|
|
17
17
|
let saving;
|
|
18
|
-
let
|
|
18
|
+
let last;
|
|
19
19
|
init().then(ok => ok || (failedOnFirstAttempt === null || failedOnFirstAttempt === void 0 ? void 0 : failedOnFirstAttempt()));
|
|
20
20
|
return {
|
|
21
21
|
unwatch() {
|
|
@@ -46,24 +46,18 @@ function watchLoad(path, parser, { failedOnFirstAttempt } = {}) {
|
|
|
46
46
|
if (doing)
|
|
47
47
|
return;
|
|
48
48
|
doing = true;
|
|
49
|
-
let data;
|
|
50
49
|
try {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return; // ignore read errors
|
|
63
|
-
}
|
|
64
|
-
if (path.endsWith('.yaml'))
|
|
65
|
-
data = yaml_1.default.parse(data);
|
|
66
|
-
await parser(data);
|
|
50
|
+
const text = await (0, misc_1.readFileBusy)(path);
|
|
51
|
+
if (text === last)
|
|
52
|
+
return;
|
|
53
|
+
last = text;
|
|
54
|
+
console.debug('loaded', path);
|
|
55
|
+
const parsed = path.endsWith('.yaml') ? yaml_1.default.parse(text) : text;
|
|
56
|
+
await parser(parsed);
|
|
57
|
+
}
|
|
58
|
+
catch (e) { // ignore read errors
|
|
59
|
+
if (e.code === 'EPERM')
|
|
60
|
+
console.error("missing permissions on file", path); // warn user, who could be clueless about this problem
|
|
67
61
|
}
|
|
68
62
|
finally {
|
|
69
63
|
doing = false;
|