hfs 3.1.5 → 3.2.0-beta2
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/af-DWEYq388.js +1 -0
- package/admin/assets/am-DgLbAgj6.js +1 -0
- package/admin/assets/ar-DgEWkO74.js +1 -0
- package/admin/assets/ar-dz-DHq--Sr8.js +1 -0
- package/admin/assets/ar-iq-D1r3nsb9.js +1 -0
- package/admin/assets/ar-kw-C85fGHwp.js +1 -0
- package/admin/assets/ar-ly-Bq6pjGjs.js +1 -0
- package/admin/assets/ar-ma-SGvmh6Mj.js +1 -0
- package/admin/assets/ar-sa-Bv8hiFi6.js +1 -0
- package/admin/assets/ar-tn-Bdvo77v3.js +1 -0
- package/admin/assets/az-7fPndoov.js +1 -0
- package/admin/assets/be-wjXeIeAK.js +1 -0
- package/admin/assets/bg-DZwBvjzH.js +1 -0
- package/admin/assets/bi-qCtxvMhO.js +1 -0
- package/admin/assets/bm-BVPWvreb.js +1 -0
- package/admin/assets/bn-CdWvye7d.js +1 -0
- package/admin/assets/bn-bd-B5-3blmz.js +1 -0
- package/admin/assets/bo-BEVcgyN2.js +1 -0
- package/admin/assets/br-DGQD6fFs.js +1 -0
- package/admin/assets/bs-So4MoRua.js +1 -0
- package/admin/assets/ca-Bk5ytG4g.js +1 -0
- package/admin/assets/cs-C4NU8eW-.js +1 -0
- package/admin/assets/cv-Ct-s-zrW.js +1 -0
- package/admin/assets/cy-ojtDPj8_.js +1 -0
- package/admin/assets/da-CYGin6vm.js +1 -0
- package/admin/assets/de-BEbJ01zH.js +1 -0
- package/admin/assets/de-at-C7UwE1rJ.js +1 -0
- package/admin/assets/de-ch-CsZ7YQc_.js +1 -0
- package/admin/assets/dv-DaVliwLd.js +1 -0
- package/admin/assets/el-DM_KqKEP.js +1 -0
- package/admin/assets/en-DedtOfaf.js +1 -0
- package/admin/assets/en-au-52Bzk5D9.js +1 -0
- package/admin/assets/en-ca-3pzEPK2N.js +1 -0
- package/admin/assets/en-gb-BrwDQS2G.js +1 -0
- package/admin/assets/en-ie-BUXSHrkL.js +1 -0
- package/admin/assets/en-il-a22drDCn.js +1 -0
- package/admin/assets/en-in-BUjecjkp.js +1 -0
- package/admin/assets/en-nz-Bbo7tnB_.js +1 -0
- package/admin/assets/en-sg-CZVDddmd.js +1 -0
- package/admin/assets/en-tt-DmSGwRia.js +1 -0
- package/admin/assets/eo-B71nkHZU.js +1 -0
- package/admin/assets/es-Dk6VCuuk.js +1 -0
- package/admin/assets/es-do-DMErY8ol.js +1 -0
- package/admin/assets/es-mx-BMRmqa3u.js +1 -0
- package/admin/assets/es-pr-CtBQz48p.js +1 -0
- package/admin/assets/es-us-CrDl5pnO.js +1 -0
- package/admin/assets/et-CO9OHqio.js +1 -0
- package/admin/assets/eu-Bip44atW.js +1 -0
- package/admin/assets/fa-CHbJ_dTM.js +1 -0
- package/admin/assets/fi-DKfoLmaQ.js +1 -0
- package/admin/assets/fo-DG1kOEfw.js +1 -0
- package/admin/assets/fr-DV73GZR4.js +1 -0
- package/admin/assets/fr-ca-BK-RoZiC.js +1 -0
- package/admin/assets/fr-ch-DjqEC5E_.js +1 -0
- package/admin/assets/fy-znrRQdeC.js +1 -0
- package/admin/assets/ga-BlZeKu0N.js +1 -0
- package/admin/assets/gd-BmrycMnC.js +1 -0
- package/admin/assets/gl-CuT8e5mi.js +1 -0
- package/admin/assets/gom-latn-BSWVd0A6.js +1 -0
- package/admin/assets/gu-BHK6LfvD.js +1 -0
- package/admin/assets/he-DPoTUevR.js +1 -0
- package/admin/assets/hi-BRuLafoW.js +1 -0
- package/admin/assets/hr-Bzge-10P.js +1 -0
- package/admin/assets/ht-Ck9BCna1.js +1 -0
- package/admin/assets/hu-CzqqbYmU.js +1 -0
- package/admin/assets/hy-am-C-eV4E8v.js +1 -0
- package/admin/assets/id-Dv8GZQvB.js +1 -0
- package/admin/assets/{index-DTxjaflW.js → index-BPIX0qPj.js} +1 -1
- package/admin/assets/index-CFWd-FDo.css +1 -0
- package/admin/assets/index-D3HviM6x.js +889 -0
- package/admin/assets/is-CK6VY3M_.js +1 -0
- package/admin/assets/it-1gtki4a5.js +1 -0
- package/admin/assets/it-ch-C0Mj3-pC.js +1 -0
- package/admin/assets/ja-Dl3AfnM1.js +1 -0
- package/admin/assets/jv-CznX-tGV.js +1 -0
- package/admin/assets/ka-BNjZxCug.js +1 -0
- package/admin/assets/kk-80J_xldf.js +1 -0
- package/admin/assets/km-CuWChDRB.js +1 -0
- package/admin/assets/kn-BZp_PBdl.js +1 -0
- package/admin/assets/ko-RirpyUl_.js +1 -0
- package/admin/assets/ku-Dz8ACD5w.js +1 -0
- package/admin/assets/ky-BN3ylOhj.js +1 -0
- package/admin/assets/lb-D7h_YoEn.js +1 -0
- package/admin/assets/lo-BrlbTUPD.js +1 -0
- package/admin/assets/lt-cXuHFdTa.js +1 -0
- package/admin/assets/lv-CjIpv13Q.js +1 -0
- package/admin/assets/me-B-jTh39Z.js +1 -0
- package/admin/assets/mi-D06xdVmt.js +1 -0
- package/admin/assets/mk-iLbuxyOf.js +1 -0
- package/admin/assets/ml-2W0y6Zb2.js +1 -0
- package/admin/assets/mn-6zbvKjeb.js +1 -0
- package/admin/assets/mr-7-jrgLyw.js +1 -0
- package/admin/assets/ms-CRH6rEXt.js +1 -0
- package/admin/assets/ms-my-BIJmu2S-.js +1 -0
- package/admin/assets/mt-CbXmxK-D.js +1 -0
- package/admin/assets/my-BvMUsxU8.js +1 -0
- package/admin/assets/nb-DvKHgF7L.js +1 -0
- package/admin/assets/ne-DiZZ3Lm6.js +1 -0
- package/admin/assets/nl-be-Dy7PYRbC.js +1 -0
- package/admin/assets/nl-t_2A_VAT.js +1 -0
- package/admin/assets/nn-Cw7EwosO.js +1 -0
- package/admin/assets/oc-lnc-CuFfB75K.js +1 -0
- package/admin/assets/pa-in-DOFyZ-Ft.js +1 -0
- package/admin/assets/pl-BD7FyCJj.js +1 -0
- package/admin/assets/pt-DSKLLE_u.js +1 -0
- package/admin/assets/pt-br-BhL4gb5Z.js +1 -0
- package/admin/assets/rn-DoHoZZPd.js +1 -0
- package/admin/assets/ro-B0v-_lH0.js +1 -0
- package/admin/assets/ru-BMVOk5eA.js +1 -0
- package/admin/assets/rw-CWF0w6eL.js +1 -0
- package/admin/assets/sd-DO2rrjch.js +1 -0
- package/admin/assets/se-CAolO9WQ.js +1 -0
- package/admin/assets/{sha512-D936QW8l.js → sha512-ZlUYj4Hr.js} +1 -1
- package/admin/assets/si-D03dHfb5.js +1 -0
- package/admin/assets/sk-_GcZGaN3.js +1 -0
- package/admin/assets/sl-Cb1lUGab.js +1 -0
- package/admin/assets/sq-Czzt23Tr.js +1 -0
- package/admin/assets/sr-D76dVqKJ.js +1 -0
- package/admin/assets/sr-cyrl-CuoFbJjW.js +1 -0
- package/admin/assets/ss-g-fGaM29.js +1 -0
- package/admin/assets/sv-CZxc8I45.js +1 -0
- package/admin/assets/sv-fi-D8REJeLz.js +1 -0
- package/admin/assets/sw-B1n3PjWG.js +1 -0
- package/admin/assets/ta-K5mexJNT.js +1 -0
- package/admin/assets/te-DT6dj5B6.js +1 -0
- package/admin/assets/tet-DXwYNm_H.js +1 -0
- package/admin/assets/tg-BCcZKcE2.js +1 -0
- package/admin/assets/th-CeeeseFX.js +1 -0
- package/admin/assets/tk-CJ6KW44d.js +1 -0
- package/admin/assets/tl-ph-DzE8lDmm.js +1 -0
- package/admin/assets/tlh-ER6KiMxG.js +1 -0
- package/admin/assets/tr-D48NGNpr.js +1 -0
- package/admin/assets/tzl-5AsmDTYM.js +1 -0
- package/admin/assets/tzm-2AzZ1YPf.js +1 -0
- package/admin/assets/tzm-latn-Cd5hPQuT.js +1 -0
- package/admin/assets/ug-cn-DU-MZ9Vx.js +1 -0
- package/admin/assets/uk-hn6vcOkn.js +1 -0
- package/admin/assets/ur-jOObtqB6.js +1 -0
- package/admin/assets/uz-BlftYfHF.js +1 -0
- package/admin/assets/uz-latn-BpuI0ccM.js +1 -0
- package/admin/assets/vi-DVo3LusT.js +1 -0
- package/admin/assets/x-pseudo-BuVzNhqi.js +1 -0
- package/admin/assets/yo-BvWGwb4m.js +1 -0
- package/admin/assets/zh-D9-tfba1.js +1 -0
- package/admin/assets/zh-cn-CFL5sbIW.js +1 -0
- package/admin/assets/zh-hk-DRP8u65r.js +1 -0
- package/admin/assets/zh-tw-CtVs1ihI.js +1 -0
- package/admin/index.html +2 -2
- package/frontend/assets/index-legacy-D3BTBYs5.js +9 -0
- package/frontend/assets/{index-legacy-vmpqwZZf.js → index-legacy-DcrWtKxQ.js} +1 -1
- package/frontend/assets/{sha512-legacy-wI89-UHR.js → sha512-legacy-DJvEwScE.js} +1 -1
- package/frontend/index.html +1 -1
- package/npm-shrinkwrap.json +144 -71
- package/package.json +9 -9
- package/plugins/antibrute/plugin.js +150 -19
- package/plugins/list-uploader/public/main.js +1 -1
- package/src/acme.js +11 -7
- package/src/api.accounts.js +3 -3
- package/src/api.auth.js +3 -1
- package/src/api.get_file_list.js +17 -13
- package/src/api.monitor.js +47 -43
- package/src/api.net.js +4 -3
- package/src/api.vfs.js +1 -1
- package/src/basicWeb.js +1 -1
- package/src/commands.js +54 -1
- package/src/comments.js +7 -4
- package/src/config.js +9 -5
- package/src/consoleLog.js +39 -1
- package/src/const.js +4 -0
- package/src/cross.js +33 -6
- package/src/errorPages.js +20 -10
- package/src/events.js +3 -3
- package/src/expiringCache.js +8 -7
- package/src/fileAttr.js +73 -15
- package/src/frontEndApis.js +20 -15
- package/src/index.js +2 -1
- package/src/langs/hfs-lang-ar.json +2 -1
- package/src/langs/hfs-lang-bg.json +2 -1
- package/src/langs/hfs-lang-de.json +2 -1
- package/src/langs/hfs-lang-el.json +2 -1
- package/src/langs/hfs-lang-es.json +2 -1
- package/src/langs/hfs-lang-fi.json +2 -1
- package/src/langs/hfs-lang-fr.json +2 -1
- package/src/langs/hfs-lang-hu.json +2 -1
- package/src/langs/hfs-lang-it.json +2 -1
- package/src/langs/hfs-lang-ja.json +2 -1
- package/src/langs/hfs-lang-ko.json +2 -1
- package/src/langs/hfs-lang-lt.json +2 -1
- package/src/langs/hfs-lang-ms.json +2 -0
- package/src/langs/hfs-lang-nl.json +2 -1
- package/src/langs/hfs-lang-pt-br.json +2 -1
- package/src/langs/hfs-lang-ro.json +2 -1
- package/src/langs/hfs-lang-ru.json +2 -1
- package/src/langs/hfs-lang-sr-latn.json +2 -1
- package/src/langs/hfs-lang-sr.json +2 -1
- package/src/langs/hfs-lang-th.json +2 -1
- package/src/langs/hfs-lang-tr.json +2 -1
- package/src/langs/hfs-lang-uk.json +2 -1
- package/src/langs/hfs-lang-vi.json +2 -1
- package/src/langs/hfs-lang-zh-tw.json +2 -1
- package/src/langs/hfs-lang-zh.json +2 -1
- package/src/listen.js +2 -1
- package/src/log.js +27 -2
- package/src/middlewares.js +8 -2
- package/src/misc.js +14 -0
- package/src/nat.js +61 -21
- package/src/outboundProxy.js +1 -1
- package/src/perm.js +5 -1
- package/src/plugins.js +34 -5
- package/src/roots.js +1 -1
- package/src/selfCheck.js +2 -1
- package/src/serveGuiAndSharedFiles.js +18 -7
- package/src/serveGuiFiles.js +2 -1
- package/src/update.js +10 -18
- package/src/urlList.js +32 -0
- package/src/util-files.js +24 -9
- package/src/util-http.js +4 -0
- package/src/vfs.js +21 -9
- package/src/walkDir.js +7 -1
- package/src/webdav.js +4 -1
- package/src/zip.js +3 -2
- package/admin/assets/index-B66w-a0v.css +0 -1
- package/admin/assets/index-Df6vYR7s.js +0 -822
- package/frontend/assets/index-legacy-emBsvICj.js +0 -9
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hfs",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0-beta2",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "hfs",
|
|
9
|
-
"version": "3.
|
|
9
|
+
"version": "3.2.0-beta2",
|
|
10
10
|
"license": "GPL-3.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@gregoranders/csv": "^0.0.13",
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
"fs-x-attributes": "^1.0.2",
|
|
22
22
|
"fswin": "^3.24.829",
|
|
23
23
|
"iconv-lite": "^0.7.0",
|
|
24
|
-
"immer": "^10.1.3",
|
|
25
24
|
"ip2location-nodejs": "^9.7.0",
|
|
26
25
|
"koa": "^3.1.2",
|
|
27
26
|
"koa-compress": "^5.2.0",
|
|
@@ -35,10 +34,11 @@
|
|
|
35
34
|
"open": "^8.4.0",
|
|
36
35
|
"picomatch": "^4.0.3",
|
|
37
36
|
"tssrp6a": "^3.0.0",
|
|
38
|
-
"
|
|
37
|
+
"unzipper": "^0.12.3",
|
|
39
38
|
"valtio": "^1.13.2",
|
|
40
39
|
"xxhashjs": "^0.2.2",
|
|
41
|
-
"yaml": "^2.8.1"
|
|
40
|
+
"yaml": "^2.8.1",
|
|
41
|
+
"yazl": "^3.3.1"
|
|
42
42
|
},
|
|
43
43
|
"bin": {
|
|
44
44
|
"hfs": "src/index.js"
|
|
@@ -404,18 +404,11 @@
|
|
|
404
404
|
],
|
|
405
405
|
"license": "MIT"
|
|
406
406
|
},
|
|
407
|
-
"node_modules/
|
|
408
|
-
"version": "
|
|
409
|
-
"resolved": "https://registry.npmjs.org/
|
|
410
|
-
"integrity": "sha512-
|
|
411
|
-
"license": "MIT"
|
|
412
|
-
"dependencies": {
|
|
413
|
-
"buffers": "~0.1.1",
|
|
414
|
-
"chainsaw": "~0.1.0"
|
|
415
|
-
},
|
|
416
|
-
"engines": {
|
|
417
|
-
"node": "*"
|
|
418
|
-
}
|
|
407
|
+
"node_modules/bluebird": {
|
|
408
|
+
"version": "3.7.2",
|
|
409
|
+
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
|
410
|
+
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
|
|
411
|
+
"license": "MIT"
|
|
419
412
|
},
|
|
420
413
|
"node_modules/braces": {
|
|
421
414
|
"version": "3.0.3",
|
|
@@ -453,12 +446,13 @@
|
|
|
453
446
|
"ieee754": "^1.1.13"
|
|
454
447
|
}
|
|
455
448
|
},
|
|
456
|
-
"node_modules/
|
|
457
|
-
"version": "0.
|
|
458
|
-
"resolved": "https://registry.npmjs.org/
|
|
459
|
-
"integrity": "sha512-
|
|
449
|
+
"node_modules/buffer-crc32": {
|
|
450
|
+
"version": "1.0.0",
|
|
451
|
+
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz",
|
|
452
|
+
"integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==",
|
|
453
|
+
"license": "MIT",
|
|
460
454
|
"engines": {
|
|
461
|
-
"node": ">=0.
|
|
455
|
+
"node": ">=8.0.0"
|
|
462
456
|
}
|
|
463
457
|
},
|
|
464
458
|
"node_modules/busboy": {
|
|
@@ -494,18 +488,6 @@
|
|
|
494
488
|
"node": ">= 0.4"
|
|
495
489
|
}
|
|
496
490
|
},
|
|
497
|
-
"node_modules/chainsaw": {
|
|
498
|
-
"version": "0.1.0",
|
|
499
|
-
"resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz",
|
|
500
|
-
"integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==",
|
|
501
|
-
"license": "MIT/X11",
|
|
502
|
-
"dependencies": {
|
|
503
|
-
"traverse": ">=0.3.0 <0.4"
|
|
504
|
-
},
|
|
505
|
-
"engines": {
|
|
506
|
-
"node": "*"
|
|
507
|
-
}
|
|
508
|
-
},
|
|
509
491
|
"node_modules/chalk": {
|
|
510
492
|
"version": "4.1.2",
|
|
511
493
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
|
@@ -608,6 +590,12 @@
|
|
|
608
590
|
"node": ">= 0.8"
|
|
609
591
|
}
|
|
610
592
|
},
|
|
593
|
+
"node_modules/core-util-is": {
|
|
594
|
+
"version": "1.0.3",
|
|
595
|
+
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
|
596
|
+
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
|
|
597
|
+
"license": "MIT"
|
|
598
|
+
},
|
|
611
599
|
"node_modules/crc": {
|
|
612
600
|
"version": "3.8.0",
|
|
613
601
|
"resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz",
|
|
@@ -736,6 +724,15 @@
|
|
|
736
724
|
"node": ">= 0.4"
|
|
737
725
|
}
|
|
738
726
|
},
|
|
727
|
+
"node_modules/duplexer2": {
|
|
728
|
+
"version": "0.1.4",
|
|
729
|
+
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
|
|
730
|
+
"integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==",
|
|
731
|
+
"license": "BSD-3-Clause",
|
|
732
|
+
"dependencies": {
|
|
733
|
+
"readable-stream": "^2.0.2"
|
|
734
|
+
}
|
|
735
|
+
},
|
|
739
736
|
"node_modules/ee-first": {
|
|
740
737
|
"version": "1.1.1",
|
|
741
738
|
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
|
@@ -957,6 +954,20 @@
|
|
|
957
954
|
"node": ">= 0.6"
|
|
958
955
|
}
|
|
959
956
|
},
|
|
957
|
+
"node_modules/fs-extra": {
|
|
958
|
+
"version": "11.3.5",
|
|
959
|
+
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.5.tgz",
|
|
960
|
+
"integrity": "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==",
|
|
961
|
+
"license": "MIT",
|
|
962
|
+
"dependencies": {
|
|
963
|
+
"graceful-fs": "^4.2.0",
|
|
964
|
+
"jsonfile": "^6.0.1",
|
|
965
|
+
"universalify": "^2.0.0"
|
|
966
|
+
},
|
|
967
|
+
"engines": {
|
|
968
|
+
"node": ">=14.14"
|
|
969
|
+
}
|
|
970
|
+
},
|
|
960
971
|
"node_modules/fs-x-attributes": {
|
|
961
972
|
"version": "1.0.2",
|
|
962
973
|
"resolved": "https://registry.npmjs.org/fs-x-attributes/-/fs-x-attributes-1.0.2.tgz",
|
|
@@ -1042,6 +1053,12 @@
|
|
|
1042
1053
|
"url": "https://github.com/sponsors/ljharb"
|
|
1043
1054
|
}
|
|
1044
1055
|
},
|
|
1056
|
+
"node_modules/graceful-fs": {
|
|
1057
|
+
"version": "4.2.11",
|
|
1058
|
+
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
|
1059
|
+
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
|
1060
|
+
"license": "ISC"
|
|
1061
|
+
},
|
|
1045
1062
|
"node_modules/has-flag": {
|
|
1046
1063
|
"version": "4.0.0",
|
|
1047
1064
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
|
@@ -1206,16 +1223,6 @@
|
|
|
1206
1223
|
],
|
|
1207
1224
|
"license": "BSD-3-Clause"
|
|
1208
1225
|
},
|
|
1209
|
-
"node_modules/immer": {
|
|
1210
|
-
"version": "10.2.0",
|
|
1211
|
-
"resolved": "https://registry.npmjs.org/immer/-/immer-10.2.0.tgz",
|
|
1212
|
-
"integrity": "sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==",
|
|
1213
|
-
"license": "MIT",
|
|
1214
|
-
"funding": {
|
|
1215
|
-
"type": "opencollective",
|
|
1216
|
-
"url": "https://opencollective.com/immer"
|
|
1217
|
-
}
|
|
1218
|
-
},
|
|
1219
1226
|
"node_modules/inherits": {
|
|
1220
1227
|
"version": "2.0.4",
|
|
1221
1228
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
|
@@ -1294,6 +1301,12 @@
|
|
|
1294
1301
|
"node": ">=8"
|
|
1295
1302
|
}
|
|
1296
1303
|
},
|
|
1304
|
+
"node_modules/isarray": {
|
|
1305
|
+
"version": "1.0.0",
|
|
1306
|
+
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
|
1307
|
+
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
|
1308
|
+
"license": "MIT"
|
|
1309
|
+
},
|
|
1297
1310
|
"node_modules/js-tokens": {
|
|
1298
1311
|
"version": "4.0.0",
|
|
1299
1312
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
|
@@ -1301,6 +1314,18 @@
|
|
|
1301
1314
|
"license": "MIT",
|
|
1302
1315
|
"peer": true
|
|
1303
1316
|
},
|
|
1317
|
+
"node_modules/jsonfile": {
|
|
1318
|
+
"version": "6.2.1",
|
|
1319
|
+
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz",
|
|
1320
|
+
"integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==",
|
|
1321
|
+
"license": "MIT",
|
|
1322
|
+
"dependencies": {
|
|
1323
|
+
"universalify": "^2.0.0"
|
|
1324
|
+
},
|
|
1325
|
+
"optionalDependencies": {
|
|
1326
|
+
"graceful-fs": "^4.1.6"
|
|
1327
|
+
}
|
|
1328
|
+
},
|
|
1304
1329
|
"node_modules/keygrip": {
|
|
1305
1330
|
"version": "1.1.0",
|
|
1306
1331
|
"resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz",
|
|
@@ -1530,18 +1555,6 @@
|
|
|
1530
1555
|
"url": "https://github.com/sponsors/ljharb"
|
|
1531
1556
|
}
|
|
1532
1557
|
},
|
|
1533
|
-
"node_modules/mkdirp": {
|
|
1534
|
-
"version": "0.5.6",
|
|
1535
|
-
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
|
|
1536
|
-
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
|
1537
|
-
"license": "MIT",
|
|
1538
|
-
"dependencies": {
|
|
1539
|
-
"minimist": "^1.2.6"
|
|
1540
|
-
},
|
|
1541
|
-
"bin": {
|
|
1542
|
-
"mkdirp": "bin/cmd.js"
|
|
1543
|
-
}
|
|
1544
|
-
},
|
|
1545
1558
|
"node_modules/ms": {
|
|
1546
1559
|
"version": "2.1.3",
|
|
1547
1560
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
|
@@ -1566,6 +1579,12 @@
|
|
|
1566
1579
|
"node": ">= 6.13.0"
|
|
1567
1580
|
}
|
|
1568
1581
|
},
|
|
1582
|
+
"node_modules/node-int64": {
|
|
1583
|
+
"version": "0.4.0",
|
|
1584
|
+
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
|
1585
|
+
"integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
|
|
1586
|
+
"license": "MIT"
|
|
1587
|
+
},
|
|
1569
1588
|
"node_modules/on-finished": {
|
|
1570
1589
|
"version": "2.4.1",
|
|
1571
1590
|
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
|
|
@@ -1631,6 +1650,12 @@
|
|
|
1631
1650
|
"url": "https://github.com/sponsors/jonschlinkert"
|
|
1632
1651
|
}
|
|
1633
1652
|
},
|
|
1653
|
+
"node_modules/process-nextick-args": {
|
|
1654
|
+
"version": "2.0.1",
|
|
1655
|
+
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
|
1656
|
+
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
|
1657
|
+
"license": "MIT"
|
|
1658
|
+
},
|
|
1634
1659
|
"node_modules/proxy-compare": {
|
|
1635
1660
|
"version": "2.6.0",
|
|
1636
1661
|
"resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.6.0.tgz",
|
|
@@ -1697,6 +1722,21 @@
|
|
|
1697
1722
|
"node": ">=0.10.0"
|
|
1698
1723
|
}
|
|
1699
1724
|
},
|
|
1725
|
+
"node_modules/readable-stream": {
|
|
1726
|
+
"version": "2.3.8",
|
|
1727
|
+
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
|
1728
|
+
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
|
1729
|
+
"license": "MIT",
|
|
1730
|
+
"dependencies": {
|
|
1731
|
+
"core-util-is": "~1.0.0",
|
|
1732
|
+
"inherits": "~2.0.3",
|
|
1733
|
+
"isarray": "~1.0.0",
|
|
1734
|
+
"process-nextick-args": "~2.0.0",
|
|
1735
|
+
"safe-buffer": "~5.1.1",
|
|
1736
|
+
"string_decoder": "~1.1.1",
|
|
1737
|
+
"util-deprecate": "~1.0.1"
|
|
1738
|
+
}
|
|
1739
|
+
},
|
|
1700
1740
|
"node_modules/reflect-metadata": {
|
|
1701
1741
|
"version": "0.2.2",
|
|
1702
1742
|
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz",
|
|
@@ -1736,6 +1776,12 @@
|
|
|
1736
1776
|
"queue-microtask": "^1.2.2"
|
|
1737
1777
|
}
|
|
1738
1778
|
},
|
|
1779
|
+
"node_modules/safe-buffer": {
|
|
1780
|
+
"version": "5.1.2",
|
|
1781
|
+
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
|
1782
|
+
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
|
1783
|
+
"license": "MIT"
|
|
1784
|
+
},
|
|
1739
1785
|
"node_modules/safer-buffer": {
|
|
1740
1786
|
"version": "2.1.2",
|
|
1741
1787
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
|
@@ -1765,6 +1811,15 @@
|
|
|
1765
1811
|
"node": ">=10.0.0"
|
|
1766
1812
|
}
|
|
1767
1813
|
},
|
|
1814
|
+
"node_modules/string_decoder": {
|
|
1815
|
+
"version": "1.1.1",
|
|
1816
|
+
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
|
1817
|
+
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
|
1818
|
+
"license": "MIT",
|
|
1819
|
+
"dependencies": {
|
|
1820
|
+
"safe-buffer": "~5.1.0"
|
|
1821
|
+
}
|
|
1822
|
+
},
|
|
1768
1823
|
"node_modules/strnum": {
|
|
1769
1824
|
"version": "2.3.0",
|
|
1770
1825
|
"resolved": "https://registry.npmjs.org/strnum/-/strnum-2.3.0.tgz",
|
|
@@ -1810,15 +1865,6 @@
|
|
|
1810
1865
|
"node": ">=0.6"
|
|
1811
1866
|
}
|
|
1812
1867
|
},
|
|
1813
|
-
"node_modules/traverse": {
|
|
1814
|
-
"version": "0.3.9",
|
|
1815
|
-
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz",
|
|
1816
|
-
"integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==",
|
|
1817
|
-
"license": "MIT/X11",
|
|
1818
|
-
"engines": {
|
|
1819
|
-
"node": "*"
|
|
1820
|
-
}
|
|
1821
|
-
},
|
|
1822
1868
|
"node_modules/tslib": {
|
|
1823
1869
|
"version": "2.8.1",
|
|
1824
1870
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
|
@@ -1889,14 +1935,26 @@
|
|
|
1889
1935
|
"url": "https://opencollective.com/express"
|
|
1890
1936
|
}
|
|
1891
1937
|
},
|
|
1892
|
-
"node_modules/
|
|
1893
|
-
"version": "0.
|
|
1894
|
-
"resolved": "https://registry.npmjs.org/
|
|
1895
|
-
"integrity": "sha512-
|
|
1938
|
+
"node_modules/universalify": {
|
|
1939
|
+
"version": "2.0.1",
|
|
1940
|
+
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
|
1941
|
+
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
|
1942
|
+
"license": "MIT",
|
|
1943
|
+
"engines": {
|
|
1944
|
+
"node": ">= 10.0.0"
|
|
1945
|
+
}
|
|
1946
|
+
},
|
|
1947
|
+
"node_modules/unzipper": {
|
|
1948
|
+
"version": "0.12.3",
|
|
1949
|
+
"resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.12.3.tgz",
|
|
1950
|
+
"integrity": "sha512-PZ8hTS+AqcGxsaQntl3IRBw65QrBI6lxzqDEL7IAo/XCEqRTKGfOX56Vea5TH9SZczRVxuzk1re04z/YjuYCJA==",
|
|
1896
1951
|
"license": "MIT",
|
|
1897
1952
|
"dependencies": {
|
|
1898
|
-
"
|
|
1899
|
-
"
|
|
1953
|
+
"bluebird": "~3.7.2",
|
|
1954
|
+
"duplexer2": "~0.1.4",
|
|
1955
|
+
"fs-extra": "^11.2.0",
|
|
1956
|
+
"graceful-fs": "^4.2.2",
|
|
1957
|
+
"node-int64": "^0.4.0"
|
|
1900
1958
|
}
|
|
1901
1959
|
},
|
|
1902
1960
|
"node_modules/use-sync-external-store": {
|
|
@@ -1908,6 +1966,12 @@
|
|
|
1908
1966
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
|
1909
1967
|
}
|
|
1910
1968
|
},
|
|
1969
|
+
"node_modules/util-deprecate": {
|
|
1970
|
+
"version": "1.0.2",
|
|
1971
|
+
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
|
1972
|
+
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
|
1973
|
+
"license": "MIT"
|
|
1974
|
+
},
|
|
1911
1975
|
"node_modules/valtio": {
|
|
1912
1976
|
"version": "1.13.2",
|
|
1913
1977
|
"resolved": "https://registry.npmjs.org/valtio/-/valtio-1.13.2.tgz",
|
|
@@ -1982,6 +2046,15 @@
|
|
|
1982
2046
|
"url": "https://github.com/sponsors/eemeli"
|
|
1983
2047
|
}
|
|
1984
2048
|
},
|
|
2049
|
+
"node_modules/yazl": {
|
|
2050
|
+
"version": "3.3.1",
|
|
2051
|
+
"resolved": "https://registry.npmjs.org/yazl/-/yazl-3.3.1.tgz",
|
|
2052
|
+
"integrity": "sha512-BbETDVWG+VcMUle37k5Fqp//7SDOK2/1+T7X8TD96M3D9G8jK5VLUdQVdVjGi8im7FGkazX7kk5hkU8X4L5Bng==",
|
|
2053
|
+
"license": "MIT",
|
|
2054
|
+
"dependencies": {
|
|
2055
|
+
"buffer-crc32": "^1.0.0"
|
|
2056
|
+
}
|
|
2057
|
+
},
|
|
1985
2058
|
"node_modules/zod": {
|
|
1986
2059
|
"version": "3.25.76",
|
|
1987
2060
|
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hfs",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0-beta2",
|
|
4
4
|
"description": "HTTP File Server",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"file server",
|
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
"build-server": "rm -rf dist/src dist/plugins && npm i && tsc && touch package.json && cp -v -r package.json central.json README* LICENSE* hfs.ico plugins dist && find dist -name .DS_Store -o -name storage -exec rm -rf {} + && node scripts/afterbuild.js",
|
|
20
20
|
"build-frontend": "npm run build --workspace=frontend",
|
|
21
21
|
"build-admin": "npm run build --workspace=admin",
|
|
22
|
-
"server-for-test": "node dist/src --cwd tests/work --config tests --debug",
|
|
22
|
+
"server-for-test": "mkdir -p tests/work && cp tests/config.yaml tests/work/config.yaml && node dist/src --cwd tests/work --config tests/work/config.yaml --debug",
|
|
23
23
|
"server-for-test-dev": "cross-env DEV=1 FRONTEND_PROXY=3005 ADMIN_PROXY=3006 nodemon --ignore tests/ --watch src -e ts,tsx --exec tsx src -- --cwd tests/work --config tests",
|
|
24
|
-
"test": "node --import tsx --test tests/test.ts",
|
|
25
|
-
"test-with-server": "sh -c 'npm run port-is-free && tsc && rm -rf tests/work tests/tmp && (node dist/src --cwd tests/work --config tests & echo $! > .server_pid) && sleep 2 && node --import tsx --test \"$@\" tests/test.ts; _exit=$?; if [ -f ./.server_pid ]; then SERVER_PID=$(cat ./.server_pid); kill \"$SERVER_PID\" 2>/dev/null || true; rm -f ./.server_pid; fi; exit $_exit' --",
|
|
24
|
+
"test": "sh -c 'npm run port-is-free >/dev/null && { echo \"no server\"; exit 1; }; node --import tsx --test \"$@\" tests/test.ts' --",
|
|
25
|
+
"test-with-server": "sh -c 'npm run port-is-free && tsc && rm -rf tests/work tests/tmp && mkdir -p tests/work && cp tests/config.yaml tests/work/config.yaml && (node dist/src --cwd tests/work --config tests/work/config.yaml & echo $! > .server_pid) && sleep 2 && node --import tsx --test \"$@\" tests/test.ts; _exit=$?; if [ -f ./.server_pid ]; then SERVER_PID=$(cat ./.server_pid); kill \"$SERVER_PID\" 2>/dev/null || true; rm -f ./.server_pid; fi; exit $_exit' --",
|
|
26
26
|
"port-is-free": "node -e \"const port=process.argv[1]||8081;process.exit(await fetch('http://localhost:'+port).then(() => console.log('BUSY')||1, () => 0))\" --",
|
|
27
27
|
"test-ui": "npm run port-is-free -- 8081 && rm -rf tests/work tests/work2 && npx playwright test frontend && npx playwright test serial && npx playwright test admin-vfs",
|
|
28
28
|
"test-with-ui": "sh -c 'npm run port-is-free -- 3005 && npm run start-frontend & npm run port-is-free -- 3006 && npm run start-admin & cross-env TEST_WITH_UI=1 npx playwright test --ui \"$@\"' --",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"dist": "STASHED=; if ! git diff-index --quiet HEAD --; then git stash push -m 'dist' && STASHED=1; fi; CI=1 FORCE_COLOR=1 npm run dist-uncommitted || (EXIT_CODE=$?; [ -n \"$STASHED\" ] && git stash pop; exit $EXIT_CODE); [ -n \"$STASHED\" ] && git stash pop",
|
|
31
31
|
"dist-uncommitted": "npm audit --omit=dev --audit-level=moderate && rm -rf dist && npm run build-server && npm run test-with-server && (npm run build-frontend & npm run build-admin) && npm run test-ui && npm run dist-bin",
|
|
32
32
|
"dist-bin": "npm run dist-modules && npm run dist-bin-win && npm run dist-bin-linux && npm run dist-bin-linux-arm && npm run dist-bin-mac && npm run dist-bin-mac-arm",
|
|
33
|
-
"dist-modules": "cp package.json central.json README.md dist && cd dist && npm pkg delete devDependencies workspaces && rm -rf node_modules && npm install --omit=dev && npm shrinkwrap && cd .. && node scripts/prune_modules.js",
|
|
33
|
+
"dist-modules": "cp package.json central.json README.md dist && cd dist && npm pkg delete devDependencies workspaces scripts.postinstall && rm -rf node_modules && npm install --omit=dev && npm shrinkwrap && cd .. && node scripts/prune_modules.js",
|
|
34
34
|
"dist-bin-win": "cd dist && pkg . --public -C gzip -t node20-win-x64 && npx resedit-cli --in hfs.exe --icon 1,../hfs.ico --out hfs.exe && zip hfs-windows-x64-$(jq -r .version ../package.json).zip hfs.exe -r plugins && cd ..",
|
|
35
35
|
"dist-bin-mac-arm": "cd dist && pkg . --public -C gzip -t node20-macos-arm64 && zip hfs-mac-arm64-$(jq -r .version ../package.json).zip hfs -r plugins && cd ..",
|
|
36
36
|
"dist-bin-mac": "cd dist && pkg . --public -C gzip -t node20-macos-x64 && zip hfs-mac-x64-$(jq -r .version ../package.json).zip hfs -r plugins && cd ..",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"**/node_modules/axios/dist/node/*",
|
|
71
71
|
"**/node_modules/buffers/**",
|
|
72
72
|
"**/node_modules/binary/**",
|
|
73
|
-
"**/node_modules/
|
|
73
|
+
"**/node_modules/unzipper/**"
|
|
74
74
|
],
|
|
75
75
|
"targets": [
|
|
76
76
|
"node20-win-x64",
|
|
@@ -93,7 +93,6 @@
|
|
|
93
93
|
"fs-x-attributes": "^1.0.2",
|
|
94
94
|
"fswin": "^3.24.829",
|
|
95
95
|
"iconv-lite": "^0.7.0",
|
|
96
|
-
"immer": "^10.1.3",
|
|
97
96
|
"ip2location-nodejs": "^9.7.0",
|
|
98
97
|
"koa": "^3.1.2",
|
|
99
98
|
"koa-compress": "^5.2.0",
|
|
@@ -107,9 +106,10 @@
|
|
|
107
106
|
"open": "^8.4.0",
|
|
108
107
|
"picomatch": "^4.0.3",
|
|
109
108
|
"tssrp6a": "^3.0.0",
|
|
110
|
-
"
|
|
109
|
+
"unzipper": "^0.12.3",
|
|
111
110
|
"valtio": "^1.13.2",
|
|
112
111
|
"xxhashjs": "^0.2.2",
|
|
113
|
-
"yaml": "^2.8.1"
|
|
112
|
+
"yaml": "^2.8.1",
|
|
113
|
+
"yazl": "^3.3.1"
|
|
114
114
|
}
|
|
115
115
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
exports.version = 3.
|
|
1
|
+
exports.version = 3.2
|
|
2
2
|
exports.description = "Introduce increasing delays between login attempts."
|
|
3
3
|
exports.apiRequired = 9.6 // addBlock
|
|
4
4
|
|
|
@@ -8,42 +8,173 @@ exports.config = {
|
|
|
8
8
|
blockAfter: { type: 'number', xs: 6, min: 1, max: 9999, defaultValue: 100, label: "Block IP after", unit: "attempts", helperText: "localhost excluded" },
|
|
9
9
|
blockForHours: { type: 'number', xs: 6, min: 0, defaultValue: 24, label: "Block for", unit: "hours" },
|
|
10
10
|
exclude: { type: 'string', defaultValue: '', label: "Exclude IPs", helperText: "Net mask syntax" },
|
|
11
|
+
maxQueuePerIp: { type: 'number', min: 1, max: 9999, defaultValue: 32, label: "Max queued per IP" },
|
|
12
|
+
maxQueuePerAccount: { type: 'number', min: 1, max: 9999, defaultValue: 16, label: "Max queued per account" },
|
|
13
|
+
maxQueueGlobal: { type: 'number', min: 1, max: 999999, defaultValue: 512, label: "Max queued globally" },
|
|
11
14
|
}
|
|
12
15
|
exports.configDialog = {
|
|
13
16
|
maxWidth: 'xs',
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
const byIp = {}
|
|
20
|
+
const byAccount = {}
|
|
21
|
+
const laneByIp = {}
|
|
22
|
+
const laneByAccount = {}
|
|
23
|
+
const UNKNOWN_ACCOUNT = 'unknown\t'
|
|
17
24
|
|
|
18
25
|
exports.init = api => {
|
|
19
26
|
const { isLocalHost, HOUR, netMatches } = api.misc
|
|
27
|
+
const { makeQ } = api.require('./makeQ')
|
|
28
|
+
const gateQ = makeQ(1)
|
|
29
|
+
let waitingGlobal = 0
|
|
30
|
+
const QUEUE_FULL = Symbol('queue_full')
|
|
20
31
|
api.events.multi({
|
|
21
|
-
async attemptingLogin({ ctx }) {
|
|
32
|
+
async attemptingLogin({ ctx, username }) {
|
|
22
33
|
const { ip } = ctx
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
const account = getAccountKey(username)
|
|
35
|
+
const ipRec = getRecord(byIp, ip)
|
|
36
|
+
const accountRec = getRecord(byAccount, account)
|
|
37
|
+
let admitted = false
|
|
38
|
+
try {
|
|
39
|
+
await runGate(() => {
|
|
40
|
+
if (ipRec.waiting >= api.getConfig('maxQueuePerIp')
|
|
41
|
+
|| accountRec.waiting >= api.getConfig('maxQueuePerAccount')
|
|
42
|
+
|| waitingGlobal >= api.getConfig('maxQueueGlobal'))
|
|
43
|
+
throw QUEUE_FULL
|
|
44
|
+
// reserve all buckets atomically so we never exceed limits due to parallel requests
|
|
45
|
+
ipRec.waiting++
|
|
46
|
+
accountRec.waiting++
|
|
47
|
+
waitingGlobal++
|
|
48
|
+
admitted = true
|
|
49
|
+
})
|
|
50
|
+
// serialize waits per ip and per account so parallel bursts can't consume the same penalty window
|
|
51
|
+
await runInLane(getLane(laneByIp, ip), () =>
|
|
52
|
+
runInLane(getLane(laneByAccount, account), async () => {
|
|
53
|
+
const now = Date.now()
|
|
54
|
+
const wait = Math.max(0, ipRec.next - now, accountRec.next - now)
|
|
55
|
+
if (wait <= 0) return
|
|
56
|
+
api.log('delaying', ip, 'for', Math.round(wait / 1000))
|
|
57
|
+
ctx.set('x-anti-brute-force', wait)
|
|
58
|
+
await new Promise(resolve => setTimeout(resolve, wait))
|
|
59
|
+
}))
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
if (e === QUEUE_FULL) {
|
|
63
|
+
ctx.status = 429
|
|
64
|
+
return api.events.stop
|
|
65
|
+
}
|
|
66
|
+
throw e
|
|
32
67
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
68
|
+
finally {
|
|
69
|
+
if (admitted) {
|
|
70
|
+
ipRec.waiting--
|
|
71
|
+
accountRec.waiting--
|
|
72
|
+
waitingGlobal--
|
|
73
|
+
}
|
|
74
|
+
armCleanup(byIp, ip, ipRec)
|
|
75
|
+
armCleanup(byAccount, account, accountRec)
|
|
76
|
+
dropLaneIfIdle(laneByIp, ip)
|
|
77
|
+
dropLaneIfIdle(laneByAccount, account)
|
|
38
78
|
}
|
|
39
|
-
|
|
79
|
+
},
|
|
80
|
+
failedLogin({ ctx, username }) {
|
|
81
|
+
const { ip } = ctx
|
|
82
|
+
const account = getAccountKey(username)
|
|
83
|
+
const now = Date.now()
|
|
84
|
+
const ipRec = getRecord(byIp, ip)
|
|
85
|
+
const accountRec = getRecord(byAccount, account)
|
|
86
|
+
const ipAttempts = increasePenalty(ipRec, now)
|
|
87
|
+
increasePenalty(accountRec, now)
|
|
88
|
+
if (ipAttempts > api.getConfig('blockAfter') && !isLocalHost(ctx) && !isExcluded(ip)) {
|
|
89
|
+
const hours = api.getConfig('blockForHours')
|
|
90
|
+
api.addBlock({ ip, comment: "From antibrute plugin", expire: hours ? new Date(now + hours * HOUR) : undefined })
|
|
91
|
+
}
|
|
92
|
+
armCleanup(byIp, ip, ipRec)
|
|
93
|
+
armCleanup(byAccount, account, accountRec)
|
|
94
|
+
dropLaneIfIdle(laneByIp, ip)
|
|
95
|
+
dropLaneIfIdle(laneByAccount, account)
|
|
40
96
|
},
|
|
41
97
|
login(ctx) {
|
|
42
|
-
if (ctx.state.account)
|
|
43
|
-
|
|
98
|
+
if (ctx.state.account) {
|
|
99
|
+
const { ip } = ctx
|
|
100
|
+
const account = getAccountKey(ctx.state.account.username)
|
|
101
|
+
resetRecord(byIp, ip)
|
|
102
|
+
resetRecord(byAccount, account)
|
|
103
|
+
dropLaneIfIdle(laneByIp, ip)
|
|
104
|
+
dropLaneIfIdle(laneByAccount, account)
|
|
105
|
+
}
|
|
44
106
|
}
|
|
45
107
|
})
|
|
46
108
|
|
|
109
|
+
function getRecord(container, key) {
|
|
110
|
+
return container[key] ||= { failures: 0, next: 0, waiting: 0 }
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function increasePenalty(rec, now) {
|
|
114
|
+
const attempts = ++rec.failures
|
|
115
|
+
const max = api.getConfig('max') * 1000
|
|
116
|
+
const delay = Math.min(max, attempts * api.getConfig('increment') * 1000)
|
|
117
|
+
rec.next = Math.max(now, rec.next) + delay
|
|
118
|
+
return attempts
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function armCleanup(records, key, rec) {
|
|
122
|
+
clearTimeout(rec.timer)
|
|
123
|
+
rec.timer = setTimeout(() => {
|
|
124
|
+
// keep records while there are in-flight admissions, otherwise later releases may touch deleted state
|
|
125
|
+
if (rec.waiting)
|
|
126
|
+
return armCleanup(records, key, rec)
|
|
127
|
+
delete records[key]
|
|
128
|
+
}, 24 * HOUR) // no memory leak
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function runGate(job) {
|
|
132
|
+
return new Promise((resolve, reject) => {
|
|
133
|
+
gateQ.add(async () => {
|
|
134
|
+
try { resolve(await job()) }
|
|
135
|
+
catch (e) { reject(e) }
|
|
136
|
+
})
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function getLane(container, key) {
|
|
141
|
+
return container[key] ||= makeQ(1)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function runInLane(q, job) {
|
|
145
|
+
return new Promise((resolve, reject) => {
|
|
146
|
+
q.add(async () => {
|
|
147
|
+
try { resolve(await job()) }
|
|
148
|
+
catch (e) { reject(e) }
|
|
149
|
+
})
|
|
150
|
+
})
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function dropLaneIfIdle(container, key) {
|
|
154
|
+
const q = container[key]
|
|
155
|
+
if (q?.isWorking() || q?.queueSize()) return
|
|
156
|
+
delete container[key]
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function resetRecord(container, key) {
|
|
160
|
+
const rec = container[key]
|
|
161
|
+
if (!rec) return
|
|
162
|
+
if (rec.waiting) {
|
|
163
|
+
// successful login must clear penalties without dropping admission counters still needed by concurrent requests
|
|
164
|
+
rec.failures = 0
|
|
165
|
+
rec.next = 0
|
|
166
|
+
return
|
|
167
|
+
}
|
|
168
|
+
delete container[key]
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function getAccountKey(username) {
|
|
172
|
+
// fold unknown usernames together to avoid unbounded memory growth from random names
|
|
173
|
+
if (!username || !api.getAccount(String(username)))
|
|
174
|
+
return UNKNOWN_ACCOUNT
|
|
175
|
+
return String(username).toLowerCase()
|
|
176
|
+
}
|
|
177
|
+
|
|
47
178
|
function isExcluded(ip) {
|
|
48
179
|
const mask = api.getConfig('exclude')
|
|
49
180
|
if (!mask) return false
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
HFS.h(Uploader, entry))
|
|
7
7
|
|
|
8
8
|
function Uploader({ uri }) {
|
|
9
|
-
const { data } = HFS.useBatch(getDetails, uri)
|
|
9
|
+
const { data } = HFS.useBatch(getDetails, uri, { depend: HFS.state.isAdmin })
|
|
10
10
|
const text = React.useMemo(() => {
|
|
11
11
|
if (!data || data === true) return ''
|
|
12
12
|
const { upload: x } = data
|