hfs 3.3.2 → 3.3.4

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 (56) hide show
  1. package/admin/assets/AccountsPage-CnZGcUox.js +6 -0
  2. package/admin/assets/{ArrayField-ChS9pNra.js → ArrayField-F7fpCJIv.js} +1 -1
  3. package/admin/assets/{ConfigFilePage-6jCYVkbr.js → ConfigFilePage-CEgZ8Wq4.js} +1 -1
  4. package/admin/assets/{CustomHtmlPage-DaEXsEcQ.js → CustomHtmlPage-DDUNxF1H.js} +1 -1
  5. package/admin/assets/{DataTable-Cf5S5yWr.js → DataTable-D_TeYxvk.js} +1 -1
  6. package/admin/assets/{DateTimeField--mTsSB1l.js → DateTimeField-CsIdkTqz.js} +1 -1
  7. package/admin/assets/{EventManager-BJWba-fL.js → EventManager--HiXIAY0.js} +1 -1
  8. package/admin/assets/{FileField-B0WhrAuk.js → FileField-HsDCdr5S.js} +1 -1
  9. package/admin/assets/{InternetPage-BICQDG_K.js → InternetPage-DDwKrXJH.js} +3 -3
  10. package/admin/assets/{LangPage-D42UPSxC.js → LangPage-Dd8hi_9K.js} +1 -1
  11. package/admin/assets/{LogsPage-DQTrf5GE.js → LogsPage-BcPfugNY.js} +1 -1
  12. package/admin/assets/{MenuButton-DDfB3119.js → MenuButton-cuehhVig.js} +1 -1
  13. package/admin/assets/{MonitorPage-CH06c8aW.js → MonitorPage-Bre9d6MA.js} +1 -1
  14. package/admin/assets/OptionsPage-Dd_cRDf4.js +3 -0
  15. package/admin/assets/PluginsPage-DJiseD4G.js +1 -0
  16. package/admin/assets/{Tabs-CGfV3BK0.js → Tabs-C87E85Fh.js} +1 -1
  17. package/admin/assets/{TextEditor-Df9LSzm6.js → TextEditor-Cr0VI9Xi.js} +1 -1
  18. package/admin/assets/{VfsPathField-6Kyy5vuQ.js → VfsPathField-D1BkfhAM.js} +1 -1
  19. package/admin/assets/{agentIcons-DwT9U-lh.js → agentIcons-CDoUTPUC.js} +1 -1
  20. package/admin/assets/{baseUrl-D7S0KsqZ.js → baseUrl-CnrV7Huu.js} +2 -2
  21. package/admin/assets/{icons-DWkdo8hc.js → icons-DJJYoK9E.js} +1 -1
  22. package/admin/assets/index-DwXlUHAs.js +477 -0
  23. package/admin/assets/{routing-CxxvyWME.js → routing-BQpoUdjq.js} +1 -1
  24. package/admin/index.html +1 -1
  25. package/frontend/assets/{dist-legacy-zQdkj0Z9.js → dist-legacy-CnYHQXZ6.js} +1 -1
  26. package/frontend/assets/index-legacy-JYULclbY.js +1 -0
  27. package/frontend/assets/{lib-legacy-CRrFEEqm.js → lib-legacy-3xYueNHt.js} +1 -1
  28. package/frontend/assets/{sha512-legacy-BB7Mdt0y.js → sha512-legacy-Cl3f_PhN.js} +1 -1
  29. package/frontend/index.html +1 -1
  30. package/npm-shrinkwrap.json +63 -63
  31. package/package.json +2 -2
  32. package/plugins/antibrute/plugin.js +13 -6
  33. package/src/adminApis.js +2 -1
  34. package/src/api.accounts.js +9 -4
  35. package/src/api.auth.js +10 -2
  36. package/src/api.net.js +2 -1
  37. package/src/api.vfs.js +2 -1
  38. package/src/auth.js +12 -7
  39. package/src/cross.js +1 -2
  40. package/src/deletePermission.js +120 -0
  41. package/src/events.js +6 -0
  42. package/src/index.js +3 -1
  43. package/src/listen.js +2 -1
  44. package/src/middlewares.js +27 -9
  45. package/src/nat.js +10 -7
  46. package/src/outboundProxy.js +1 -1
  47. package/src/perm.js +26 -4
  48. package/src/serveGuiAndSharedFiles.js +3 -2
  49. package/src/sessionStamp.js +53 -0
  50. package/src/uploadOwners.js +4 -2
  51. package/src/vfs.js +72 -34
  52. package/admin/assets/AccountsPage-Cvi9DSc1.js +0 -3
  53. package/admin/assets/OptionsPage-BvXLA_R0.js +0 -3
  54. package/admin/assets/PluginsPage-CyaVJZkM.js +0 -1
  55. package/admin/assets/index-BDdPG215.js +0 -477
  56. package/frontend/assets/index-legacy-B8EvbIOB.js +0 -1
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sessionStampsReady = void 0;
4
+ exports.getSessionStamp = getSessionStamp;
5
+ exports.renewSessionStamp = renewSessionStamp;
6
+ exports.syncSessionStamps = syncSessionStamps;
7
+ const persistence_1 = require("./persistence");
8
+ const node_crypto_1 = require("node:crypto");
9
+ const stamps = new Map();
10
+ const prefix = 'sessionStamp:';
11
+ // random signing keys already invalidate all cookies on restart
12
+ const persistent = process.env.COOKIE_SIGN_KEYS !== undefined;
13
+ exports.sessionStampsReady = load();
14
+ function getSessionStamp(username) {
15
+ return stamps.get(username)?.stamp;
16
+ }
17
+ function renewSessionStamp(username) {
18
+ const current = stamps.get(username);
19
+ if (current)
20
+ setStamp(username, current.credentials);
21
+ }
22
+ function syncSessionStamps(accounts) {
23
+ for (const username of stamps.keys())
24
+ if (!(username in accounts)) {
25
+ stamps.delete(username);
26
+ if (persistent)
27
+ void persistence_1.storedMap.del(prefix + username);
28
+ }
29
+ for (const [username, account] of Object.entries(accounts)) {
30
+ // compare values across reloads and restarts without duplicating credentials in data.kv
31
+ const credentials = (0, node_crypto_1.createHash)('sha256').update(JSON.stringify([
32
+ account?.srp, account?.password, account?.plugin,
33
+ ])).digest('hex');
34
+ if (stamps.get(username)?.credentials !== credentials)
35
+ setStamp(username, credentials);
36
+ }
37
+ }
38
+ function setStamp(username, credentials) {
39
+ const stamp = `${Date.now()}.${Math.floor(Math.random() * 1000).toString().padStart(3, '0')}`;
40
+ const record = { stamp, credentials };
41
+ stamps.set(username, record);
42
+ // accepted tradeoff: with fixed signing keys, a crash before this delayed write may lose a revocation
43
+ if (persistent)
44
+ void persistence_1.storedMap.put(prefix + username, record);
45
+ }
46
+ async function load() {
47
+ for await (const [key, record] of persistence_1.storedMap.iterator({ startsWith: prefix })) {
48
+ if (persistent)
49
+ stamps.set(key.slice(prefix.length), record);
50
+ else // re-enabling the same signing keys later must not revive cookies revoked during this run
51
+ void persistence_1.storedMap.del(key);
52
+ }
53
+ }
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.uploadOwners = exports.ownUploadDeleteHours = void 0;
7
+ exports.grantUploadOwnerDelete = grantUploadOwnerDelete;
7
8
  exports.isUnfinishedUploadOwner = isUnfinishedUploadOwner;
8
9
  exports.setUploadOwner = setUploadOwner;
9
10
  exports.moveUploadOwner = moveUploadOwner;
@@ -33,7 +34,8 @@ setInterval(() => {
33
34
  void exports.uploadOwners.del(k);
34
35
  }
35
36
  }, misc_1.MINUTE);
36
- events_1.default.on('checkVfsPermission', ({ node, perm, ctx }) => {
37
+ events_1.default.on('checkVfsPermission', grantUploadOwnerDelete);
38
+ function grantUploadOwnerDelete({ node, perm, ctx }) {
37
39
  if (perm !== 'can_delete' || !node.source)
38
40
  return;
39
41
  const { vfsPath } = node;
@@ -49,7 +51,7 @@ events_1.default.on('checkVfsPermission', ({ node, perm, ctx }) => {
49
51
  }
50
52
  if (matchesOwner(owner, ctx))
51
53
  return 0;
52
- });
54
+ }
53
55
  function matchesOwner(owner, ctx) {
54
56
  const username = (0, auth_1.getCurrentUsername)(ctx);
55
57
  const { sessionId } = owner;
package/src/vfs.js CHANGED
@@ -27,6 +27,7 @@ exports.simpleWhoToError = simpleWhoToError;
27
27
  exports.walkNode = walkNode;
28
28
  exports.masksCouldGivePermission = masksCouldGivePermission;
29
29
  exports.parentMaskApplier = parentMaskApplier;
30
+ exports.renameUnderPath = renameUnderPath;
30
31
  const promises_1 = __importDefault(require("fs/promises"));
31
32
  const path_1 = require("path");
32
33
  const misc_1 = require("./misc");
@@ -222,11 +223,16 @@ async function getNodeByName(name, parent, assumeMissingToBeFolder = false) {
222
223
  ret.source = (0, path_1.join)(parent.source, onDisk);
223
224
  ret.original = undefined; // this will overwrite the 'original' set in applyParentToChild, so we know this is not part of the vfs
224
225
  await setIsFolder(ret);
226
+ if (ret.isFolder === false && isCommentsFileName(onDisk))
227
+ return; // implicit comment storage contains metadata for files the requester may not be allowed to see
225
228
  if (assumeMissingToBeFolder)
226
229
  ret.isFolder ??= true;
227
230
  return ret;
228
231
  }
229
232
  }
233
+ function isCommentsFileName(name) {
234
+ return (0, comments_1.usingDescriptIon)() && [comments_1.DESCRIPT_ION, comments_1.DESCRIPT_ION_ALT].some(isSameFilenameAs(name));
235
+ }
230
236
  const smartUncFolderDetection = (0, config_1.defineConfig)(misc_1.CFG.smart_unc_folder_detection, false);
231
237
  async function setIsFolder(node) {
232
238
  if (!node.source)
@@ -326,7 +332,7 @@ function nodeIsLink(node) {
326
332
  function hasPermission(node, perm, ctx) {
327
333
  return !statusCodeForMissingPerm(node, perm, ctx, false);
328
334
  }
329
- function statusCodeForMissingPerm(node, perm, ctx, assign = true) {
335
+ function statusCodeForMissingPerm(node, perm, ctx, assign = true, checkListeners = true) {
330
336
  const ret = getCode();
331
337
  if (ret && assign) {
332
338
  ctx.status = ret;
@@ -356,7 +362,7 @@ function statusCodeForMissingPerm(node, perm, ctx, assign = true) {
356
362
  } while (1);
357
363
  if ((0, misc_1.isWhoObject)(who) || isWhoVfsPerms(who))
358
364
  throw Error(`permission type-guard: ${JSON.stringify(who)}`);
359
- const first = lodash_1.default.max(events_1.default.emit('checkVfsPermission', { who, node, perm, ctx }));
365
+ const first = checkListeners ? lodash_1.default.max(events_1.default.emit('checkVfsPermission', { who, node, perm, ctx })) : undefined;
360
366
  if (first !== undefined)
361
367
  return first;
362
368
  return simpleWhoToError(who, ctx)
@@ -385,7 +391,6 @@ async function* walkNode(parent, { ctx, depth = Infinity, prefixPath = '', requi
385
391
  started = true;
386
392
  const { source } = parent;
387
393
  const taken = new Set();
388
- const maskApplier = parentMaskApplier(parent);
389
394
  const visitLater = [];
390
395
  const childrenWorking = parent.children?.length && Promise.all(parent.children.map(async (child) => {
391
396
  if (ctx?.isAborted())
@@ -394,7 +399,7 @@ async function* walkNode(parent, { ctx, depth = Infinity, prefixPath = '', requi
394
399
  const name = prefixPath + nodeName;
395
400
  taken?.add(normalizeFilename(name));
396
401
  const item = setVfsPath({ ...child, original: child, name, parent }, name, parent);
397
- if (await cantSee(item))
402
+ if (await cantSee(item, parent, nodeName))
398
403
  return;
399
404
  if (item.source && !item.children?.length && !item.see_without_probing) // real items must be accessible, unless probing was explicitly disabled
400
405
  try {
@@ -404,11 +409,10 @@ async function* walkNode(parent, { ctx, depth = Infinity, prefixPath = '', requi
404
409
  return;
405
410
  }
406
411
  const isFolder = nodeIsFolder(child);
407
- if (onlyFiles ? !isFolder : (!onlyFolders || isFolder))
412
+ if (canEmit(item, isFolder))
408
413
  stream.push(item);
409
414
  if (!depth || !isFolder || cantRecur(item))
410
415
  return;
411
- inheritMasks(item, parent);
412
416
  visitLater.push([item, name]); // prioritize siblings
413
417
  }));
414
418
  try {
@@ -418,30 +422,51 @@ async function* walkNode(parent, { ctx, depth = Infinity, prefixPath = '', requi
418
422
  && !hasPermission(parent, requiredPerm, ctx)
419
423
  && !masksCouldGivePermission(parent.masks, requiredPerm))
420
424
  return;
421
- const pathMaskApplier = parentMaskApplier(parent, true);
425
+ const diskFolders = new Map();
426
+ diskFolders.set('', { node: parent, virtualPath: '' });
427
+ const applyPathMask = parentMaskApplier(parent, true, true);
428
+ const applyRootNameMask = parentMaskApplier(parent, false, true);
422
429
  try {
423
430
  await (0, walkDir_1.walkDir)(source, { depth, ctx, hidden: showHiddenFiles.get(), parallelizeRecursion }, async (entry) => {
424
431
  if (ctx?.isAborted())
425
432
  return null;
426
- if ((0, comments_1.usingDescriptIon)() && (entry.name === comments_1.DESCRIPT_ION || entry.name === comments_1.DESCRIPT_ION_ALT))
427
- return;
428
433
  const { path } = entry; // this path is not the original deprecated property: we are overwriting/reusing it
429
434
  const isFolder = entry.isDirectory();
430
- let renamed = parent.rename?.[path];
431
- if (renamed) {
432
- const dir = (0, path_1.dirname)(path); // if `path` isn't just the name, copy its dir in renamed
433
- if (dir !== '.')
434
- renamed = dir + '/' + renamed;
435
- }
436
- const name = prefixPath + (renamed || path);
437
- if (taken?.has(normalizeFilename(name))) // taken by vfs node above
435
+ if (!isFolder && isCommentsFileName(entry.name))
436
+ return;
437
+ const parentPath = (0, path_1.dirname)(path) === '.' ? '' : (0, path_1.dirname)(path);
438
+ const evaluatedParent = diskFolders.get(parentPath);
439
+ if (!evaluatedParent)
440
+ return false;
441
+ const physicalName = (0, path_1.basename)(path);
442
+ const virtualName = evaluatedParent.node.rename?.[physicalName] || physicalName;
443
+ const virtualPath = evaluatedParent.virtualPath
444
+ ? evaluatedParent.virtualPath + '/' + virtualName
445
+ : virtualName;
446
+ const name = prefixPath + virtualPath;
447
+ if (taken.has(normalizeFilename(name))) // taken by vfs node above
438
448
  return false; // false just in case it's a folder
439
- const item = setVfsPath({ name, isFolder, source: (0, path_1.join)(source, path), parent, stats: entry.stats }, name, parent);
440
- // masks containing '/' must be matched against the relative path while keeping walkDir recursion enabled
441
- await pathMaskApplier(item, renamed || path);
442
- if (await cantSee(item)) // can't see: don't produce and don't recur
449
+ const item = setVfsPath({
450
+ name: virtualName,
451
+ isFolder,
452
+ source: (0, path_1.join)(source, path),
453
+ parent: evaluatedParent.node,
454
+ rename: renameUnderPath(evaluatedParent.node.rename, physicalName),
455
+ stats: entry.stats,
456
+ }, virtualName, evaluatedParent.node);
457
+ const rootMaskProperties = { isFolder };
458
+ const exceptions = applyPathMask(rootMaskProperties, virtualPath);
459
+ for (const key of applyRootNameMask(rootMaskProperties, virtualName))
460
+ exceptions.add(key);
461
+ for (const key of exceptions)
462
+ if (!(key in rootMaskProperties))
463
+ rootMaskProperties[key] = parent[key];
464
+ if (await cantSee(item, evaluatedParent.node, virtualName, rootMaskProperties)) // can't see: don't produce and don't recur
443
465
  return false;
444
- if (onlyFiles ? !isFolder : (!onlyFolders || isFolder))
466
+ if (isFolder)
467
+ diskFolders.set(path, { node: item, virtualPath });
468
+ item.name = name;
469
+ if (canEmit(item, isFolder))
445
470
  stream.push(item);
446
471
  if (cantRecur(item))
447
472
  return false;
@@ -464,10 +489,16 @@ async function* walkNode(parent, { ctx, depth = Infinity, prefixPath = '', requi
464
489
  function cantRecur(item) {
465
490
  return ctx && !hasPermission(item, 'can_list', ctx);
466
491
  }
492
+ function canEmit(item, isFolder) {
493
+ return !(requiredPerm && ctx && !hasPermission(item, requiredPerm, ctx))
494
+ && (onlyFiles ? !isFolder : (!onlyFolders || isFolder));
495
+ }
467
496
  // item will be changed, so be sure to pass a temp node
468
- async function cantSee(item) {
469
- await maskApplier(item);
497
+ async function cantSee(item, itemParent, virtualName, pathPermissions) {
498
+ inheritMasks(item, itemParent, virtualName);
499
+ await parentMaskApplier(itemParent)(item, virtualName);
470
500
  inheritFromParent(item);
501
+ Object.assign(item, pathPermissions);
471
502
  if (ctx && !hasPermission(item, 'can_see', ctx))
472
503
  return true;
473
504
  item.isTemp = true;
@@ -484,7 +515,7 @@ async function* walkNode(parent, { ctx, depth = Infinity, prefixPath = '', requi
484
515
  function masksCouldGivePermission(masks, perm) {
485
516
  return masks !== undefined && Object.values(masks).some(props => props[perm] || masksCouldGivePermission(props.masks, perm));
486
517
  }
487
- function parentMaskApplier(parent, pathBased = false) {
518
+ function parentMaskApplier(parent, pathBased = false, trackExceptions = false) {
488
519
  // rules are met in the parent.masks object from nearest to farthest, but since we finally apply with _.defaults, the nearest has precedence in the final result
489
520
  const matchers = (0, misc_1.onlyTruthy)(lodash_1.default.map(parent.masks, (mods, mask) => {
490
521
  if (!mods)
@@ -502,11 +533,6 @@ function parentMaskApplier(parent, pathBased = false) {
502
533
  if (pathBased) {
503
534
  if (!mask.includes('/'))
504
535
  return;
505
- // avoid evaluating twice masks like **/*.png because parentMaskApplier already handles them by basename
506
- const m = /^(!?)\*\*\//.exec(mask);
507
- // this keeps the fast basename path as source-of-truth for patterns that collapse to a filename after **/
508
- if (m && !mask.slice(m[0].length).includes('/'))
509
- return;
510
536
  }
511
537
  else {
512
538
  const m = /^(!?)\*\*\//.exec(mask); // ** globstar matches also zero subfolders, so this mask must be applied here too
@@ -514,22 +540,34 @@ function parentMaskApplier(parent, pathBased = false) {
514
540
  if (!mask)
515
541
  return;
516
542
  }
517
- return mask && { matcher: (0, misc_1.makeMatcher)(mask), mods, mustBeFolder };
543
+ return mask && {
544
+ matcher: (0, misc_1.makeMatcher)(mask),
545
+ exceptionMatcher: trackExceptions && mask.startsWith('!') ? (0, misc_1.makeMatcher)(mask.slice(1)) : undefined,
546
+ mods,
547
+ mustBeFolder,
548
+ };
518
549
  }));
519
550
  return (item, virtualName = (pathBased ? lodash_1.default.identity : path_1.basename)(getNodeName(item))) => {
520
551
  // depth traversal passes full relative paths, while node traversal still matches only basenames
552
+ const exceptions = new Set();
521
553
  let isFolder = undefined;
522
- for (const { matcher, mods, mustBeFolder } of matchers) {
554
+ for (const { matcher, exceptionMatcher, mods, mustBeFolder } of matchers) {
523
555
  if (mustBeFolder !== undefined) {
524
556
  isFolder ??= nodeIsFolder(item);
525
557
  if (mustBeFolder !== isFolder)
526
558
  continue;
527
559
  }
528
- if (!matcher(virtualName))
560
+ if (!matcher(virtualName)) {
561
+ if (exceptionMatcher?.(virtualName))
562
+ for (const key of misc_1.PERM_KEYS)
563
+ if (mods[key] !== undefined && !(key in item))
564
+ exceptions.add(key);
529
565
  continue;
566
+ }
530
567
  item.masks &&= lodash_1.default.merge(lodash_1.default.cloneDeep(mods.masks), item.masks); // item.masks must take precedence
531
568
  lodash_1.default.defaults(item, mods);
532
569
  }
570
+ return exceptions;
533
571
  };
534
572
  }
535
573
  // propagates masks, don't apply
@@ -539,7 +577,7 @@ function inheritMasks(item, parent, virtualBasename = getNodeName(item)) {
539
577
  return;
540
578
  const o = {};
541
579
  for (const [k, v] of Object.entries(masks)) {
542
- if (k.startsWith('**')) {
580
+ if (/^!?\*\*/.test(k)) {
543
581
  o[k] = v;
544
582
  continue;
545
583
  }
@@ -1,3 +0,0 @@
1
- import{i as e}from"./rolldown-runtime-CacB07dV.js";import{t}from"./DateTimeField--mTsSB1l.js";import{n,r,t as i}from"./MenuButton-DDfB3119.js";import{n as a,t as o}from"./VfsPathField-6Kyy5vuQ.js";import{Bn as s,C as c,Ct as l,Da as u,E as d,Ea as f,Et as p,F as m,Ft as h,H as g,Ir as _,Lt as v,M as y,Ma as b,N as x,O as S,Oa as C,Pa as w,R as T,S as E,St as D,Ta as O,U as k,Ut as A,W as j,Wr as M,Yt as N,_ as ee,_i as P,_r as te,ai as F,en as I,fr as L,ft as R,gt as ne,ht as re,it as ie,j as ae,jr as oe,ka as se,lr as z,lt as ce,mt as B,ni as le,nr as ue,q as de,ri as fe,st as pe,tr as me,tt as V,vi as H,w as he,y as U,zt as ge}from"./index-BDdPG215.js";import{$ as _e,J as ve,Q as ye,X as be,Y as xe,Z as Se,et as W,it as Ce,nt as we,rt as G,tt as Te}from"./icons-DWkdo8hc.js";var K=e(w());u();var Ee=[`password`,`password2`,`adminActualAccess`,`hasPassword`,`invalidated`,`canLogin`,`members`];function De({account:e,done:n,groups:r,addToBar:i,reload:a}){var u,m;let{username:h}=ie(),[_,v]=(0,K.useState)(e),[x,S]=(0,K.useState)([]),C=I();(0,K.useEffect)(()=>{var t;v(e),S(r.filter(t=>t!==e.username)),C||(t=k.current)==null||(t=t.querySelector(`input`))==null||t.focus()},[JSON.stringify(e)]);let w=!e.username,{isGroup:T}=_,k=(0,K.useRef)(),{members:A}=e,j=(u=e.plugin)==null?void 0:u.auth;return(0,K.createElement)(ce,{key:e.username,formRef:k,values:_,set(e,t){v(n=>f(f({},n),{},{[t]:e}))},barSx:f({gap:2,width:`100%`},de()),stickyBar:!0,addToBar:[!w&&(0,K.createElement)(c,f(f({icon:G,title:`Delete`,confirm:`Delete ${e.username}?`},h===e.username&&{disabled:!0,title:`Cannot delete current account`}),{},{onClick:()=>z(`del_account`,{username:e.username}).then(a)})),(0,K.createElement)(c,{icon:xe,title:`Invalidate past sessions${s(`
2
- (already invalidated sessions before `,D(e.invalidated||0),`)`)}`,confirm:`Invalidate all sessions up to now for "${e.username}"?`,doneMessage:!0,onClick:()=>z(`invalidate_sessions`,{username:e.username}).then(a)}),...me(i)],fields:[{k:`username`,label:T?`Group name`:void 0,autoComplete:`off`,required:!0,md:T&&!j?12:4,getError:t=>t!==e.username&&z(`get_account`,{username:t}).then(t=>(t==null?void 0:t.username)===e.username?`usernames are case-insensitive`:`already used`,()=>!1)},j&&{k:``,md:8,comp:(0,K.createElement)(H,{severity:`info`},` Authentication handled by a plugin`)},!T&&!j&&{k:`password`,xs:6,md:4,type:`password`,autoComplete:`new-password`,required:w,label:w?`Password`:`Change password`},!T&&!j&&{k:`password2`,xs:6,md:4,type:`password`,autoComplete:`new-password`,label:`Repeat password`,getError:(e,{values:t})=>(e||``)!==(t.password||``)&&`Enter same password`},{k:`disabled`,comp:R,fromField:e=>!e,toField:e=>!e,label:`Enabled`,xs:12,sm:6,lg:4,helperText:_.disabled||_.canLogin!==!1?`Login is prevented if account is disabled, or all its groups are disabled`:(0,K.createElement)(F,{sx:{color:`warning.main`},component:`span`},new Date(e.expire)<new Date?`Login is prevented because account is expired`:`Login is prevented because all of its groups are disabled`)},{k:`ignore_limits`,comp:R,xs:12,sm:6,lg:4,helperText:_.ignore_limits?`Speed limits don't apply to this account`:`Speed limits apply to this account`},f({k:`admin`,comp:R,fromField:e=>e||null,label:`Admin-panel access`,xs:12,sm:6,lg:4,helperText:`To access THIS interface you are using right now`},!e.admin&&e.adminActualAccess&&{value:!0,disabled:!0,helperText:`This permission is inherited. To disable it, act on the groups.`}),!T&&{k:`require_password_change`,comp:R,xs:12,sm:6,lg:4,helperText:`At next login, but can be dismissed`},{k:`disable_password_change`,label:`Password change`,comp:ne,xs:12,sm:6,lg:4,defaultValue:null,options:{[`Default (${_.canChangePassword?`Allowed`:`Disabled`})`]:null,Allowed:!1,Disabled:!0}},A?T&&!A.length?(0,K.createElement)(F,{},`No members`):A.length>0&&(0,K.createElement)(E,{gap:0,flexWrap:`wrap`},`${A.length} members: `,N(`,\xA0`,(m=e.members)==null?void 0:m.map(e=>(0,K.createElement)(r.includes(e)?`i`:`span`,{},e))),(0,K.createElement)(U,{icon:G,confirm:`Delete ${e.members.length} accounts?`,onClick:()=>z(`del_account`,{username:e.members}).then(a),sx:{verticalAlign:`text-top`}})):null,T&&(0,K.createElement)(H,{severity:`info`},`To add users to this group, select the user and then click "Inherit"`),{k:`belongs`,comp:re,label:`Inherit from groups`,options:x,sm:6,lg:4,helperText:`Specify groups to inherit permissions from`+(T?`. A group can inherit from another group`:``)+(x.length?``:`. Now disabled because there are no groups to select, create one first.`)},{k:`allow_net`,comp:d,label:`Allowed network address`,sm:6,lg:4,placeholder:`any address`},!T&&{k:`auto_login_net`,comp:d,label:`Auto-login by IP address`,sm:6,lg:4,placeholder:`none`},{k:`redirect`,comp:o,placeholder:`no`,sm:6,lg:4,helperText:`If you want this account to be redirected to a specific folder/address (or even file) at login time`},{k:`expire`,label:`Expiration`,sm:6,lg:4,comp:t,toField:e=>e&&new Date(e),helperText:`When expired, login won't be allowed`},f(f({k:`days_to_live`,sm:6,lg:4,comp:B,step:`any`,min:1/1e3},_.expire&&{xs:12,disabled:!0,sx:{opacity:.2}}),{},{helperText:`Used to set expiration on first login`}),{k:`notes`,multiline:!0,sm:6,lg:4}],onError:g,save:f(f({},y(l(_,e))),{},{onClick(){return b(function*(){var t;let{password:r=``,password2:i,adminActualAccess:a,hasPassword:o,invalidated:s,canLogin:c,members:l}=_,u=O(_,Ee),d=((t=k.current)==null?void 0:t.querySelector(`button.saveBtn`))||void 0;if(w){let e=yield z(`add_account`,u);if(r)try{yield p(_.username,r)}catch(e){throw z(`del_account`,{username:_.username}),e}n(e==null?void 0:e.username,d);return}let m=yield z(`set_account`,{username:e.username,changes:u});r&&(yield p(_.username,r),v(e=>f(f({},e),{},{password:``,password2:``}))),e.username===h&&(V.username=m.username),n(m==null?void 0:m.username,d)})()}})})}var q=e(L());se(),u();var J={fieldSeparator:`,`,lineSeparator:`
3
- `,quote:`"`},Y={field:0,fieldOffset:0,line:0,lineOffset:0,quoted:!1,appendCell:!1,appendField:!1,appendRow:!1},X=class extends Error{constructor(e,t){super(`Invalid CSV at ${e}:${t}`)}},Oe=class{constructor(e=J){C(this,`_rows`,[]),C(this,`_row`,[]),C(this,`_cell`,``),C(this,`_options`,J),C(this,`_state`,f({},Y)),C(this,`_index`,0),C(this,`_current`,``),C(this,`_previous`,``),C(this,`_quoteState`,f({},Y)),this._options=Object.assign({},J,e)}parse(e){for(this.reset(),this._index=0;this._index<e.length;this._index++)this._state.appendCell=!0,this._previous=this._current,this._current=e[this._index],this.handleNext();if(this._row.length>0&&(this.addField(this.fieldValue(this._cell),this._row,this._state),this.addRow(this._row,this._rows,this._state)),this._state.quoted)throw new X(this._quoteState.line,this._quoteState.lineOffset);return this.makeImmutable(),this._rows}get rows(){return this._rows}get json(){if(this.rows.length>0){let e=this.rows[0].filter(e=>typeof e==`string`);return Object.freeze(this.rows.filter((e,t)=>e&&t>0).map(t=>{let n={};return e.forEach((e,r)=>{n[e]=t[r]}),Object.freeze(n)}))}return Object.freeze([])}handleNext(){this.handleQuote()||this.handleFieldSeparator()||this.handleLineSeparator(),this.processState()}handleQuote(){return this._current===this._options.quote?(this._quoteState=f({},this._state),this._previous===`\\`?this.handleQuoteEscaped():this.handleQuoteNotEscaped(),!0):!1}handleQuoteEscaped(){this._cell=this._cell.slice(0,Math.max(0,this._cell.length-1))}handleQuoteNotEscaped(){if(this._cell.length===0||this._state.quoted)this._state.quoted=!this._state.quoted;else throw new X(this._state.line,this._state.lineOffset);this._state.appendCell=!1}handleFieldSeparator(){return this._current===this._options.fieldSeparator?(this._state.quoted||(this._state.appendCell=!1,this._state.appendField=!0),!0):!1}handleLineSeparator(){return this._current===this._options.lineSeparator?(this._state.quoted||(this._state.appendCell=!1,this._state.appendField=!0,this._state.appendRow=!0),!0):!1}processState(){this._state.appendCell&&(this._cell+=this._current),this._state.appendField&&(this.addField(this.fieldValue(this._cell),this._row,this._state),this._cell=``),this._state.appendRow&&(this.addRow(this._row,this._rows,this._state),this._row=[]),this._state.lineOffset++,this._state.fieldOffset++}fieldValue(e){return e}addField(e,t,n){t.push(e),n.field++,n.fieldOffset=-1,n.appendField=!1}addRow(e,t,n){t.push(e),n.field=0,n.line++,n.lineOffset=-1,n.appendRow=!1}makeImmutable(){this.rows.forEach(e=>{e.forEach(e=>Object.freeze(e)),Object.freeze(e)}),Object.freeze(this._rows)}reset(){this._rows=[],this._row=[],this._cell=``,this._state=f({},Y),this._index=0,this._current=``,this._previous=``,this._quoteState=f({},Y)}};u();function ke(e){return Z.apply(this,arguments)}function Z(){return Z=b(function*(e){v(function(){var t=b(function*(t){let n=t==null?void 0:t[0];if(!n)return;let r=yield h(n);if(!r)return;let i=new Oe().parse(r.trim()),a={comp:B,min:1,max:9,xs:6,typing:!0},o={skipFirstLines:0,usernameColumn:1,passwordColumn:2,groupColumn:3,redirectColumn:4,overwriteExistingAccounts:!1},c=yield j({title:`Import accounts from CSV`,dialogProps:{maxWidth:`sm`},values:o,form:e=>{let t=i[e.skipFirstLines||0]||[],n=u(t,f(f({},o),e));return{save:{startIcon:(0,K.createElement)(ve),children:`Go`},fields:[(0,K.createElement)(F,{sx:{p:1}},`Total lines:`,i.length),{k:`skipFirstLines`,comp:B,max:i.length-1,typing:!0,md:6,getError:e=>e!=null&&!Number.isInteger(e)&&`Enter an integer`,helperText:(0,K.createElement)(K.Fragment,{},`First line: `,(0,K.createElement)(`code`,{},t.join(`, `)))},{k:`overwriteExistingAccounts`,comp:R,md:6},f(f({k:`usernameColumn`},a),{},{helperText:(0,K.createElement)(K.Fragment,{},`First username: `,n.u)}),f(f({k:`passwordColumn`},a),{},{helperText:(0,K.createElement)(K.Fragment,{},`First password: `,n.p)}),f(f({k:`groupColumn`},a),{},{helperText:(0,K.createElement)(K.Fragment,{},`First group: `,n.g)}),f(f({k:`redirectColumn`},a),{},{helperText:(0,K.createElement)(K.Fragment,{},`First redirect: `,n.r)})]}}});if(!c)return;let{close:l}=A({title:`Importing...`,Content(){let[t,n]=(0,K.useState)(0),[r,a]=(0,K.useState)();return(0,K.useEffect)(()=>{let t=!1;return setTimeout(b(function*(){if(t)return;let r=0,o=0,d=c.skipFirstLines,f=i.length-d,m=0;try{for(let e of i){var h;if(t)return;if(d){d--;continue}let i=u(e,c);a(i),n(m++/f),yield z(`add_account`,{username:i.u,belongs:(h=i.g)==null?void 0:h.split(`,`),redirect:i.r,overwrite:c.overwriteExistingAccounts}).then(()=>{if(i.p)return p(i.u,i.p)}).catch(e=>{if(e.code===409)return o++;r++})}}finally{l();let t=m-r-o;g(`Results: `+[s(``,r,` failed`),s(``,t,` succeeded`),s(``,o,` skipped because already present`)].filter(Boolean).join(`, `),!t&&r?`error`:r||o?`warning`:`success`),e==null||e()}})),()=>{t=!0}},[]),(0,K.createElement)(F,{sx:{display:`flex`,gap:2,alignItems:`center`}},(0,K.createElement)(he,{icon:W,progress:t}),r==null?void 0:r.u)}});function u(e,t){return{u:e[t.usernameColumn-1],p:e[t.passwordColumn-1],g:e[t.groupColumn-1],r:e[t.redirectColumn-1]}}});return function(e){return t.apply(this,arguments)}}(),{multiple:!1,accept:`.csv`})}),Z.apply(this,arguments)}u();var Ae=` `,Q=e=>e==null?void 0:e.split(Ae).at(-1);function je(){let{username:e,accountsAsTree:t}=ie(),{data:o,reload:s,element:l}=ee(`get_accounts`),[u,d]=(0,K.useState)([]),p=Array.isArray(u);(0,K.useEffect)(()=>{Array.isArray(o==null?void 0:o.list)&&p&&d(u.filter(e=>o.list.find(t=>(t==null?void 0:t.username)===Q(e))))},[o]);let h=(0,K.useMemo)(()=>o&&q.default.sortBy(o.list,[e=>!e.isGroup,e=>!e.adminActualAccess,`username`]),[o]),v=p&&q.default.find(h,{username:Q(u[0])}),y=m(`md`),C=!(u.length>0)||!h?null:p&&u.length>1?(0,K.createElement)(K.Fragment,{},(0,K.createElement)(E,{},(0,K.createElement)(P,{variant:`h6`},u.length+` selected`),(0,K.createElement)(U,{onClick:I,icon:G},`Remove`)),(0,K.createElement)(_,{},q.default.uniq(u.map(Q)).map(e=>(0,K.createElement)(a,{key:e},(0,K.createElement)(oe,{},e))))):ue(v||j(),e=>(0,K.createElement)(De,{account:e,groups:h.filter(e=>e.isGroup).map(e=>e.username),addToBar:y&&[(0,K.createElement)(F,{sx:{flex:1}}),$(e,{fontSize:`large`,sx:{p:1}}),(0,K.createElement)(c,{icon:pe,title:`Close`,onClick:N})],reload:s,done(e,t){d(y?[e]:[]),s(),S(``,t)}}));(0,K.useEffect)(()=>{if(y||!C||!u.length)return;let{close:e}=A({title:q.default.isString(u)?q.default.startCase(u):u.length>1?`Multiple selection`:v?(v.isGroup?`Group: `:`User: `)+v.username:`?`,Content:()=>C,onClose(e){e||N()}});return()=>void e(!0)},[y,u,v]);let w={height:`100%`,display:`flex`,flexDirection:`column`,overflow:`auto`},[D,O]=T(`Show tree`,`Show list`,()=>({icon:te}),t);return V.accountsAsTree=D,l||(0,K.createElement)(M,{container:!0,sx:{rowSpacing:1,columnSpacing:2,top:0,flex:`1 1 auto`,height:0}},(0,K.createElement)(M,{size:{xs:12,md:5,lg:4,xl:5},sx:w},(0,K.createElement)(F,{sx:{display:`flex`,flexWrap:`wrap`,gap:2,mb:2,boxShadow:e=>`0px -8px 4px 10px ${e.palette.background.paper}`,position:`sticky`,top:0,zIndex:2,backgroundColor:`background.paper`,width:`fit-content`}},(0,K.createElement)(i,{variant:`contained`,startIcon:(0,K.createElement)(Se),items:[{children:`user`,onClick:()=>d(`new-user`)},{children:`group`,onClick:()=>d(`new-group`)},{children:`from CSV`,onClick:()=>ke(s)}]},`Add`),x(s),O,(h==null?void 0:h.length)>0&&(0,K.createElement)(P,{sx:{p:1}},`${h.length} account(s)`)),!(h!=null&&h.length)&&(0,K.createElement)(H,{severity:`info`},ge`To access administration <u>remotely</u> you will need to create a user account with admin permission`),(0,K.createElement)(r,{multiSelect:!0,sx:{pr:4,pb:2,minWidth:`15em`},selectedItems:p?u:[],slots:{collapseIcon:Te,expandIcon:Ce},onSelectedItemsChange(e,t){var n,r;!(e==null||(n=e.target)==null||(r=n.closest)==null)&&r.call(n,`.MuiTreeItem-iconContainer`)||d(t)}},h&&(function e(t,r=``){return t.map(t=>{var i,a;return(0,K.createElement)(n,{key:t.username,itemId:r+t.username,label:(0,K.createElement)(F,{sx:{display:`flex`,flexWrap:`wrap`,padding:`.2em 0`,columnGap:`.5em`,alignItems:`center`}},$(t),(t.disabled||t.canLogin===!1)&&ae(we,t.disabled?`Disabled`:`Disabled by its groups`,t.disabled?void 0:{color:`text.secondary`}),(t.expire||t.days_to_live)&&(0,K.createElement)(be),t.adminActualAccess&&ae(_e,`Can login into Admin`),t.username,!!((i=t.belongs)!=null&&i.length)&&(0,K.createElement)(F,{sx:{color:`text.secondary`,fontSize:`small`}},`(`,(a=t.belongs)==null?void 0:a.join(`, `),`)`))},D&&e(h.filter(e=>{var n;return(n=t.directMembers)==null?void 0:n.includes(e.username)}),r+t.username+Ae))})})(D?h.filter(e=>!h.some(t=>{var n;return(n=t.members)==null?void 0:n.includes(e.username)})):h))),y&&C&&(0,K.createElement)(M,{size:`grow`,sx:f(f({},w),{},{maxWidth:`100%`})},(0,K.createElement)(fe,{sx:{overflow:`initial`}},(0,K.createElement)(le,{},C))));function j(){return{username:``,hasPassword:u===`new-user`,adminActualAccess:!1,invalidated:void 0,canLogin:!0,canChangePassword:!0,isGroup:u===`new-group`,members:[],directMembers:[]}}function N(){d([])}function I(){return L.apply(this,arguments)}function L(){return L=b(function*(){if(typeof u==`string`||u.some(t=>Q(t)===e)&&!(yield k(`You cannot ask to delete the account you are using. Continue with the rest?`)))return;let t=q.default.without(q.default.uniq(u.map(Q)),e);if(!t.length)return g(`Nothing to delete`,`info`);if(!(yield k(`Delete ${t.length} item(s)?`)))return;let n=[];for(let e of t)(yield z(`del_account`,{username:e}).then(()=>1,()=>0))||n.push(e);if(s(),n.length)return g(`The following items couldn't be deleted: `+n.join(`, `),`error`)}),L.apply(this,arguments)}}function $(e,t={}){return(0,K.createElement)(e.isGroup?W:ye,t)}export{je as default};
@@ -1,3 +0,0 @@
1
- import{i as e}from"./rolldown-runtime-CacB07dV.js";import{a as t,t as n}from"./Tabs-CGfV3BK0.js";import{Ca as r,D as i,Da as a,E as o,Ea as s,F as c,Gt as l,H as u,K as d,Kn as f,Kr as p,Kt as m,M as h,Ma as g,O as ee,Pa as _,Qn as v,Qt as y,Rt as b,T as te,Tt as ne,U as x,Wt as re,_ as S,_t as C,a as ie,ai as w,an as ae,at as oe,bn as se,fr as T,ft as E,gt as D,h as ce,ii as O,in as k,ir as A,it as le,j as ue,lr as de,lt as fe,m as pe,mt as j,nr as M,on as me,p as he,tt as N,yt as ge,z as P,zt as F}from"./index-BDdPG215.js";import{w as _e}from"./icons-DWkdo8hc.js";import{n as ve,r as I}from"./TextEditor-Df9LSzm6.js";import{t as L}from"./ArrayField-ChS9pNra.js";import{t as ye}from"./routing-CxxvyWME.js";import{r as be,t as R}from"./FileField-B0WhrAuk.js";var z=e(_()),B=e(T()),V=`//---`;function xe(e){let t=e.split(RegExp(`(?:^|
2
- )`+B.default.escapeRegExp(V),`g`)),n=[],r=!0;for(let e of t)if(r){r=!1;let t=e.trim();t&&n.push({name:``,code:t})}else{let[t,r]=f(`
3
- `,e);n.push({name:t,code:r})}return n}var H=I();a();var U,Se=[`net`,`frontend`,`uploads`,`others`],Ce=l({changes:{}});m(N,e=>{e.some(e=>e[1][0]===`config`)&&we()});function W(){var e,a,l;let{data:f,reload:p,element:m}=S(`get_config`,{omit:[`vfs`]}),_=le(),{changes:C}=re(Ce),T=S(f&&`get_status`),I=T.data,W=T.reload,Oe=()=>ce(e=>{U&&Object.assign(U,e),setTimeout(W,1e3),setTimeout(W,2e3)});(0,z.useEffect)(()=>void W(),[f]);let ke=c(`sm`),Ae=(0,z.useRef)(null),je=y(),[Me,Ne]=ye(`options`,Se),G={},Pe=(e=S(`get_admins`).data)==null?void 0:e.list,K=I==null?void 0:I.connectionAddress,q=window.location.hostname===`localhost`,Fe=K==null?void 0:K.includes(`:`),J=[{label:`any`,value:``,disabled:!1},{label:`any IPv4`,value:`0.0.0.0`,disabled:!q&&(!K||Fe)},{label:`any IPv6`,value:`::`,disabled:!q&&(!K||!Fe)},...[`127.0.0.1`,`::1`].map(e=>({label:e,value:e,disabled:!q&&K!==e})),...(I==null||(a=I.ips)==null?void 0:a.map(e=>({value:e,disabled:K!==e})))||[]];if(m)return m;if(T.error)return T.element;let Y=U===f?_.config:N.config=U=f,Ie={comp:j,min:1,unit:`KB/s`,placeholder:`no limit`,sm:6},X={comp:j,placeholder:`no limit`,toField:e=>e||``,sm:4},Z=Y[A.https_port]>=0;return(0,z.createElement)(fe,{sx:{maxWidth:`60em`},values:Y,set(e,t){N.config[t]=e},stickyBar:!0,onError:u,onValidation(e,t){if(!t)return;let n=e&&Object.keys(e).find(t=>e[t]);n&&G[n]!==void 0&&Ne(G[n])},save:s({ref:Ae,onClick:Q},h(Object.keys(C).length>0)),barSx:{gap:2},addToBar:[(0,z.createElement)(O,{onClick(){p(),W()},startIcon:(0,z.createElement)(ge)},`Reload`),(0,z.createElement)(O,{component:r,href:`/config`,startIcon:(0,z.createElement)(_e)},ke?`Config file`:`File`)],defaults(){return{xs:6}},fields:Le({Net:[{k:A.port,comp:Te,xs:12,sm:4,label:`HTTP port`,status:(I==null?void 0:I.http)||!0,suggestedPort:80},{k:A.https_port,comp:Te,xs:12,sm:4,label:`HTTPS port`,status:(I==null?void 0:I.https)||!0,suggestedPort:443,onChange(e){return e>=0&&!Z&&!Y[A.cert]&&Oe(),e}},{k:A.upnp_enabled,comp:E,xs:12,sm:4,label:`UPnP/SSDP`,helperText:`Port forwarding and double-NAT detection`},Z&&{k:A.cert,comp:R,sm:4,label:`HTTPS certificate file`,helperText:P(`HTTPS#certificate`,`What is this?`),error:M(I==null?void 0:I.https.error,e=>he(e)&&(I.https.listening?e:[e,` - `,(0,z.createElement)(te,{key:`fix`,onClick:Oe},`make one`)]))},Z&&s({k:A.private_key,comp:R,sm:4,label:`HTTPS private key file`},M(I==null?void 0:I.https.error,e=>pe(e)?{error:!0,helperText:e}:null)),Z&&{k:A.force_https,comp:E,label:`Force HTTPS`,sm:4,disabled:!Z||Y[A.port]<0,helperText:`Not applied to localhost. Doesn't work with proxies.`},{k:A.listen_interface,comp:D,sm:4,afterList:J.some(e=>e.disabled)&&(0,z.createElement)(w,{sx:{p:`8px 16px 0`,borderTop:`1px solid`,fontSize:`small`}},`If an address is disabled, connect through it to select it`),options:J},s(s({k:A.max_kbps},Ie),{},{sm:4,label:`Limit output`,helperText:`Doesn't apply to localhost`}),s(s({k:A.max_kbps_per_ip},Ie),{},{sm:4,label:`Limit output per-IP`}),s(s({k:A.max_downloads},X),{},{helperText:`Number of simultaneous downloads`}),s(s({k:A.max_downloads_per_ip},X),{},{label:`Max downloads per-IP`}),s(s({k:A.max_downloads_per_account},X),{},{label:`Max downloads per-account`,helperText:`Overrides other limits`}),{k:A.admin_net,comp:o,xs:12,sm:6,label:`Admin-panel accessible from`,placeholder:`any address`,helperText:`IP address of browser machine – localhost is an exception`},{k:A.localhost_admin,comp:E,xs:12,sm:6,label:`Consider localhost access as Admin`,getError:e=>!e&&(Pe==null?void 0:Pe.length)===0&&`First create at least one admin account`,helperText:`Access admin-panel without entering credentials`},{k:A.proxies,comp:j,xs:6,md:3,max:9,label:`Number of incoming HTTP proxies`,placeholder:`none`,error:ie(Y,I),helperText:`Necessary to detect users' IP`},{k:A.outbound_interface,comp:D,xs:6,md:3,options:[{label:`automatic`,value:``},...(I==null||(l=I.ips)==null?void 0:l.map(e=>({value:e})))||[]]},{k:A.outbound_proxy,xs:6,md:4,placeholder:`none`,helperText:`URL form`,getError:e=>v(()=>e&&new URL(e)&&``,()=>`Invalid URL`)},{k:A.allowed_referer,comp:Ee,md:2,placeholder:`any`,label:`Links from other websites`,helperText:`In case another website is linking your files`},{k:A.block,label:!1,comp:L,xs:12,prepend:!0,sm:!0,autoRowHeight:!0,form:{sx:{maxWidth:`40em`}},fields:[{k:`ip`,label:`Blocked IP`,sm:12,required:!0,wrap:!0,$width:2,comp:o,$column:{mergeRender:{comment:{},expire:{}}},helperText:`Be careful to not kick yourself out, by blocking also your IP`},{k:`expire`,$type:`dateTime`,minDate:new Date,sm:6,$hideUnder:`sm`,helperText:`Leave empty for no expiration`},{k:`disabled`,$type:`boolean`,label:`Enabled`,helperText:`In case you want to not block without deleting the rule`,toField:e=>!e,fromField:e=>e?void 0:!0,sm:6,$width:80},{k:`comment`,$hideUnder:`sm`}]}],"Front-end":[{k:A.file_menu_on_link,comp:D,label:`Access file menu`,md:3,options:{"by clicking on file name":!0,"by dedicated button":!1}},{k:A.menu_at_top,comp:D,md:3,label:`Menu panel`,options:{"at top":!0,"at bottom":!1}},{k:A.title,md:6,helperText:`You can see this in the tab of your browser`},{k:A.auto_play_seconds,comp:j,xs:6,sm:3,min:1,max:1e4,required:!0,label:`Auto-play seconds delay`,helperText:F(`Default value for the [Show interface](${k}discussions/270)`)},{k:A.tile_size,comp:j,xs:6,sm:3,max:10,required:!0,label:`Default tiles size`,helperText:P(`Tiles`,`To enable tiles-mode`)},{k:A.theme,comp:D,xs:6,sm:3,options:me},{k:A.sort_by,comp:D,xs:6,sm:3,options:ae},{k:A.invert_order,comp:E,xs:6,md:3},{k:A.folders_first,comp:E,xs:6,md:3},{k:A.sort_numerics,comp:E,xs:6,md:3,label:`Sort numeric names`},{k:A.title_with_path,comp:E,xs:6,md:3},{k:A.favicon,comp:R,placeholder:`None`,fileMask:`*.ico|`+ne,xs:12,sm:6,helperText:`The icon associated to your website`},{k:A.show_uploader,label:`Show uploader to`,comp:be,xs:!0},{k:A.page_size,comp:j,xs:!0,min:1,required:!0,helperText:`Entries per page`}],Uploads:[{k:A.dont_overwrite_uploading,comp:E,md:4,label:`Uploads don't overwrite`,helperText:`Files are automatically numbered (frontend only)`},{k:A.split_uploads,comp:j,unit:`MB`,md:2,step:.1,min:.1,fromField:e=>e*1e6,toField:e=>e?e/1e6:null,placeholder:`disabled`,label:`Split uploads in chunks`,helperText:`Overcome proxy limits (frontend only)`},{k:A.delete_unfinished_uploads_after,comp:j,md:3,min:0,unit:`seconds`,required:!0},{k:A.min_available_mb,comp:j,md:3,min:0,unit:`MBytes`,placeholder:`None`,label:`Min. available disk space`,helperText:`Reject uploads that don't comply`},{k:A.own_upload_delete_hours,comp:j,xs:12,sm:6,md:3,min:0,unit:`hours`,required:!0,label:`Uploaders can delete their files for`,helperText:`Set to 0 to disable`}],Others:[{k:A.show_hidden_files,comp:E,sm:3,label:`Include hidden files`},{k:A.descript_ion_encoding,sm:3,label:`Encoding of file DESCRIPT.ION`,comp:D,disabled:Y[A.comments_storage]===`attr`,options:[`utf8`,720,775,819,850,852,862,869,874,808,...B.default.range(1250,1257),10029,20866,21866]},{k:A.comments_storage,comp:D,xs:12,sm:6,options:{"in file DESCRIPT.ION":``,"in file attributes":`attr`,"in file attributes + load DESCRIPT.ION":`attr+ion`}},{k:A.keep_session_alive,comp:E,sm:6,md:6,helperText:`Keeps you logged in while the page is left open and the computer is on`},{k:A.session_duration,comp:j,sm:3,md:3,min:5,unit:`seconds`,required:!0},{k:A.size_1024,label:`KB size`,comp:D,sm:3,options:{1e3:!1,1024:!0}},{k:A.open_browser_at_start,comp:E,label:`Open Admin-panel at start`,xs:12,sm:6,md:3,helperText:`Browser is automatically launched with HFS`},{k:A.zip_calculate_size_for_seconds,comp:j,xs:12,sm:6,md:3,unit:`seconds`,required:!0,label:`Calculate ZIP size for`,helperText:`If time is not enough, the browser will not show download percentage`},{k:A.mime,comp:L,label:`Custom MIME types`,reorder:!0,prepend:!0,xs:12,sm:12,md:6,fields:[{k:`v`,label:`Mime type`,placeholder:`auto`,$width:2,helperText:`Leave empty to get automatic value`},{k:`k`,label:`File mask`,helperText:(0,z.createElement)(i),$width:1,$column:{renderCell:({value:e,id:t})=>(0,z.createElement)(`code`,{},e,e===`*`&&t<B.default.size(Y[A.mime])-1&&ue(oe,F("Mime with `*` should be the last, because first matching row applies"),{color:`warning.main`,ml:1}))}}],toField:e=>Object.entries(e||{}).map(([e,t])=>({k:e,v:t})),fromField:e=>Object.fromEntries(e.map(e=>[e.k,e.v||`auto`])),helperText:`Most MIME types are detected automatically`},{k:A.force_webdav_login,comp:De,sm:!0,label:`WebDAV force login`,fallbackRE:`Microsoft-WebDAV`,helperText:[`Force login for clients that mishandle mixed anonymous/protected access. `,P(`webdav`,`Why?`)]},Y[A.force_webdav_login]!==!0&&{k:A.webdav_initial_auth,comp:De,sm:6,label:`WebDAV initial auth`,helperText:`Force login only once. Used only when previous option does not match`},{k:A.server_code,comp:L,xs:12,fields:[{k:`name`,$width:.4,$render:({value:e})=>e.trim()||(0,z.createElement)(`i`,{},`no name`)},{k:`code`,comp:ve,lang:`js`,$hideUnder:`sm`,$render:({value:e})=>typeof e==`string`?(0,z.createElement)(b,{},(0,H.highlight)(e,H.languages.js,`js`)):`?`,helperText:F(`This code works similarly to [a plugin](${k}blob/main/dev-plugins.md) (with some limitations)`)}],toField:e=>!e||typeof e!=`string`?[]:xe(e),fromField:Re,applyButton:{onClick:e=>Q({[A.server_code]:Re(e)})}}]})});function Le(e){let r=Object.entries(e),i=[];for(let[e,[,t]]of r.entries())for(let n of t){if(!n){i.push(n);continue}G[n.k]=e,i.push(s(s({},n),{},{parentProps:s(s({},n.parentProps),{},{hidden:e!==Me})}))}return[{k:``,xs:12,comp:(0,z.createElement)(n,{value:Me,variant:`scrollable`,scrollButtons:`auto`,onChange(e,t){Ne(t)}},r.map(([e])=>(0,z.createElement)(t,{key:e,label:e,sx:{minWidth:0}}))),parentProps:{ref:je,sx:{position:`sticky`,top:{xs:56,sm:64,lg:0},zIndex:2,bgcolor:`background.paper`}}},...i]}function Re(e){return e.map(({name:e=``,code:t=``},n)=>n||e?`${V}${e}\n${t}\n`:t).join(``)}function Q(){return $.apply(this,arguments)}function $(){return $=g(function*(e={}){var t,n;let r=s(s({},C),e);if(B.default.isEmpty(r))return d(`Nothing to save`);let i=window.location,a=[A.port,A.https_port];if(a.every(e=>r[e]!==void 0))return u(`You cannot change both http and https port at once. Please, do one, save, and then do the other.`,`warning`);let o=[I==null||(t=I.http)==null?void 0:t.listening,I==null||(n=I.https)==null?void 0:n.listening],c=location.protocol===`https:`;c&&(a.reverse(),o.reverse());let l=r[a[0]],p=Y[a[1]],m=p>0&&o[1],h=c?`http`:`https`;if(l<0&&!m)return u(`You cannot switch off this port unless you have a working fixed port for `+h,`warning`);if(l===0&&!m)return u(`You cannot randomize this port unless you have a working fixed port for `+h,`warning`);let g=l>0&&l!=i.port;if(g&&!(yield x(`You are changing the port and you may be disconnected`)))return;let _=A.cert in r||A.private_key in r;if(c&&_&&!(yield x(`You may disrupt https service, kicking you out`)))return;yield de(`set_config`,{values:r}),A.split_uploads in r&&(yield u(`Users need to reload for the "split uploads" option to take effect`,`warning`));let v=se(i.hostname),y=i.pathname+i.hash,b=l<=0?`${c?`http:`:`https:`}//${v}:${p}${y}`:g?`${i.protocol}//${v}:${l||Y[a[0]]}${y}`:yield M(`https://${v}:${i.port}${y}`,e=>{var t;return!c&&((t=r[A.force_https])==null?f[A.force_https]:t)&&fetch(e).then(()=>e,()=>0)});if(b)return yield u(`You are being redirected but in some cases this may fail. Hold on tight!`,`warning`),window.location.href=b;let te=A.port in r||A.https_port in r;setTimeout(W,te||_?1e3:0),Object.assign(U,r),we(),ee(!1,Ae.current)}),$.apply(this,arguments)}}function we(){let e={};if(N.config)for(let[t,n]of Object.entries(N.config))JSON.stringify(n)!==JSON.stringify(U==null?void 0:U[t])&&(e[t]=n);Ce.changes=e}function Te({label:e,value:t,onChange:n,setApi:r,status:i,suggestedPort:a=1,error:o,helperText:s}){var c;let l=(0,z.useRef)(a);t>0&&(l.current=t);let u=Number(t>0?l.current:t)||0,d=i==null?void 0:i.error;return d&&(he(d)||pe(d)?d=void 0:o=!0),(0,z.createElement)(w,{},(0,z.createElement)(w,{sx:{display:`flex`}},(0,z.createElement)(D,{sx:{flexGrow:1},label:e,error:o,value:u,options:[{label:`off`,value:-1},{label:`random`,value:0},{label:`choose`,value:l.current}],onChange:n}),t>0&&(0,z.createElement)(j,{label:`Number`,fullWidth:!1,value:t,onChange:n,setApi:r,error:o,min:1,max:65535,helperText:s,sx:{minWidth:`5.5em`}})),i&&(0,z.createElement)(p,{error:o},i===!0?`...`:(c=d)==null?(i==null?void 0:i.listening)&&`Correctly working on port `+i.port:c))}function Ee({label:e,value:t,onChange:n,error:r}){let a=!t||t===`-`,o=`example.com`;return(0,z.createElement)(w,{sx:{display:`flex`}},(0,z.createElement)(D,{label:e,value:a?t:o,options:{"allow all":``,"forbid all":`-`,"allow some":o},onChange:n,error:r,sx:a?void 0:{maxWidth:`11em`}}),!a&&(0,z.createElement)(C,{label:`Domain to allow`,value:t,placeholder:`example.com`,onChange:n,error:r,helperText:(0,z.createElement)(i)}))}function De({label:e,value:t,onChange:n,error:r,helperText:i,fallbackRE:a=`.*`}){let[o,s]=(0,z.useState)(``),c=typeof t==`string`;(0,z.useEffect)(()=>s(c?t:a),[t]);let l=(0,z.useId)();return(0,z.createElement)(w,{},(0,z.createElement)(w,{sx:{display:`flex`}},(0,z.createElement)(D,{label:e,value:t,onChange:n,error:r,"aria-describedby":l,options:{Off:!1,Always:!0,RegEx:o},sx:c?{maxWidth:`9em`}:void 0}),c&&(0,z.createElement)(C,{label:`User-Agent regex`,value:t,onChange:n,error:r})),(0,z.createElement)(p,{id:l},i))}export{W as default};
@@ -1 +0,0 @@
1
- import{i as e}from"./rolldown-runtime-CacB07dV.js";import{a as t,i as n,r,t as i}from"./DataTable-Cf5S5yWr.js";import{t as a}from"./DateTimeField--mTsSB1l.js";import{a as o,t as s}from"./Tabs-CGfV3BK0.js";import{t as c}from"./VfsPathField-6Kyy5vuQ.js";import{$i as l,Bn as u,Bt as d,C as f,Da as p,E as ee,Ea as m,H as te,K as h,L as ne,Ma as g,Mn as re,Pa as ie,Rr as ae,Rt as oe,S as _,Ta as v,Tn as se,U as ce,Ut as le,W as ue,Xt as de,Zn as fe,_ as pe,_n as me,_t as y,ai as b,ar as he,bt as ge,c as _e,ea as x,er as ve,fr as ye,ft as be,ga as S,gt as C,ha as w,ht as T,ia as xe,ir as E,it as Se,j as D,l as O,lr as k,ma as A,mn as j,mt as Ce,na as M,nn as we,o as N,oa as P,pr as Te,rr as F,s as Ee,tr as De,tt as Oe,u as ke,un as I,v as L,va as Ae,wi as je,xt as Me,y as R,zt as z}from"./index-BDdPG215.js";import{$ as Ne,K as Pe,R as Fe,a as Ie,et as Le,g as Re,i as ze,n as Be,o as Ve,r as He,rt as Ue,s as We,t as Ge}from"./icons-DWkdo8hc.js";import{t as B}from"./ArrayField-ChS9pNra.js";import{t as Ke}from"./routing-CxxvyWME.js";import{t as qe}from"./FileField-B0WhrAuk.js";function Je(e){return w(`MuiTable`,e)}A(`MuiTable`,[`root`,`stickyHeader`]);var V=e(ie(),1),H=Ae();p();var Ye=[`className`,`component`,`padding`,`size`,`stickyHeader`],Xe=e=>{let{classes:t,stickyHeader:n}=e;return P({root:[`root`,n&&`stickyHeader`]},Je,t)},Ze=M(`table`,{name:`MuiTable`,slot:`Root`,overridesResolver:(e,t)=>{let{ownerState:n}=e;return[t.root,n.stickyHeader&&t.stickyHeader]}})(x(({theme:e})=>({display:`table`,width:`100%`,borderCollapse:`collapse`,borderSpacing:0,"& caption":m(m({},e.typography.body2),{},{padding:e.spacing(2),color:(e.vars||e).palette.text.secondary,textAlign:`left`,captionSide:`bottom`}),variants:[{props:({ownerState:e})=>e.stickyHeader,style:{borderCollapse:`separate`}}]}))),U=`table`,Qe=V.forwardRef(function(e,n){let r=l({props:e,name:`MuiTable`}),{className:i,component:a=U,padding:o=`normal`,size:s=`medium`,stickyHeader:c=!1}=r,u=v(r,Ye),d=m(m({},r),{},{component:a,padding:o,size:s,stickyHeader:c}),f=Xe(d),p=V.useMemo(()=>({padding:o,size:s,stickyHeader:c}),[o,s,c]);return(0,H.jsx)(t.Provider,{value:p,children:(0,H.jsx)(Ze,m({as:a,role:a===U?null:`table`,ref:n,className:S(f.root,i),ownerState:d},u))})});function $e(e){return w(`MuiTableBody`,e)}A(`MuiTableBody`,[`root`]),p();var et=[`className`,`component`],tt=e=>{let{classes:t}=e;return P({root:[`root`]},$e,t)},nt=M(`tbody`,{name:`MuiTableBody`,slot:`Root`})({display:`table-row-group`}),rt={variant:`body`},W=`tbody`,it=V.forwardRef(function(e,t){let r=l({props:e,name:`MuiTableBody`}),{className:i,component:a=W}=r,o=v(r,et),s=m(m({},r),{},{component:a}),c=tt(s);return(0,H.jsx)(n.Provider,{value:rt,children:(0,H.jsx)(nt,m({className:S(c.root,i),as:a,ref:t,role:a===W?null:`rowgroup`,ownerState:s},o))})});function at(e){return w(`MuiTableRow`,e)}var G=A(`MuiTableRow`,[`root`,`selected`,`hover`,`head`,`footer`]);p();var ot=[`className`,`component`,`hover`,`selected`],st=e=>{let{classes:t,selected:n,hover:r,head:i,footer:a}=e;return P({root:[`root`,n&&`selected`,r&&`hover`,i&&`head`,a&&`footer`]},at,t)},ct=M(`tr`,{name:`MuiTableRow`,slot:`Root`,overridesResolver:(e,t)=>{let{ownerState:n}=e;return[t.root,n.head&&t.head,n.footer&&t.footer]}})(x(({theme:e})=>({color:`inherit`,display:`table-row`,verticalAlign:`middle`,outline:0,[`&.${G.hover}:hover`]:{backgroundColor:(e.vars||e).palette.action.hover},[`&.${G.selected}`]:{backgroundColor:e.alpha((e.vars||e).palette.primary.main,(e.vars||e).palette.action.selectedOpacity),"&:hover":{backgroundColor:e.alpha((e.vars||e).palette.primary.main,`${(e.vars||e).palette.action.selectedOpacity} + ${(e.vars||e).palette.action.hoverOpacity}`)}}}))),K=`tr`,lt=V.forwardRef(function(e,t){let r=l({props:e,name:`MuiTableRow`}),{className:i,component:a=K,hover:o=!1,selected:s=!1}=r,c=v(r,ot),u=V.useContext(n),d=m(m({},r),{},{component:a,hover:o,selected:s,head:u&&u.variant===`head`,footer:u&&u.variant===`footer`});return(0,H.jsx)(ct,m({as:a,ref:t,className:S(st(d).root,i),role:a===K?null:`row`,ownerState:d},c))}),q=e(ye());p();var ut=[`type`,`defaultValue`,`frontend`,`showIf`],dt=[`value`,`onChange`,`multiple`,`groups`];function ft(e,t){return J.apply(this,arguments)}function J(){return J=g(function*(e,t){let{id:n}=e,{config:r}=yield k(`get_plugin`,{id:n}),i=q.default.some(I(e.config,r),{type:`array`})?`min(100%, ${t})`:void 0,a=!!e.config,o=yield ue({title:a?`Options for ${n}`:`Log for ${n}`,form:(t,{submit:n})=>({before:e.description&&(0,V.createElement)(b,{sx:{mx:2,mb:2}},e.description),fields:Y(I(e.config,t)||{},t),save:a?{children:`Save and close`}:!1,barSx:{gap:1},onError:te,addToBar:[(0,V.createElement)(R,{variant:`outlined`,onClick:()=>n(s)},`Save`)]}),values:r,dialogProps:q.default.merge({maxWidth:`md`,sx:{m:`auto`}},e.configDialog,{maxWidth:!1,sx:{maxWidth:null}}),Wrapper({children:e}){let{list:r,setList:o}=L(`get_plugin_log`,{id:n},{map(e){e.ts=new Date(e.ts)}}),s;return(0,V.createElement)(_,{alignItems:`stretch`,justifyContent:`center`,flexWrap:`wrap`,flexDirection:a?void 0:`column`},(0,V.createElement)(b,{sx:{maxWidth:t,width:i,minWidth:`min-content`}},e),(0,V.createElement)(je,{elevation:1,sx:{position:`relative`,fontFamily:`monospace`,flex:1,minWidth:`min(40em, 90vw)`,minHeight:`20em`,px:.5}},(0,V.createElement)(b,{sx:{my:.5,pb:.5,borderBottom:`1px solid`,display:`flex`,alignItems:`center`,justifyContent:`space-between`}},`Output`,(0,V.createElement)(R,{size:`small`,sx:{p:0},onClick(){o([])}},`Clear`)),(0,V.createElement)(b,{ref:de(r),sx:{position:`absolute`,bottom:0,top:`31px`,left:0,right:0,overflowY:`auto`}},!r.length&&(0,V.createElement)(b,{sx:{p:1}},`Log is empty`),(0,V.createElement)(b,{sx:{textIndent:`-1em`,pl:`1em`,position:`absolute`,width:`calc(100% - 1.2em)`,ml:`2px`,pt:`.2em`}},r.map(e=>{j(e.ts);let t=j(e.ts);return(0,V.createElement)(V.Fragment,{key:e.id},t!==s&&(s=t),(0,V.createElement)(b,{},(0,V.createElement)(b,{title:t,sx:{display:`inline`,color:`text.secondary`,mr:1}},me(e.ts)),d(e.msg,/https?:\/\/\S+/,e=>(0,V.createElement)(ae,{href:e[0],target:`_blank`},e[0]))))})))))}});if(o&&!q.default.isEqual(r,o))return s(o);function s(e){return c.apply(this,arguments)}function c(){return c=g(function*(e){yield k(`set_plugin`,{id:n,config:e}),Object.assign(r,e),h(`Configuration saved`)}),c.apply(this,arguments)}}),J.apply(this,arguments)}function Y(e,t){return Object.entries(e).map(([e,n])=>{if(!n)return;let{type:r,defaultValue:i,frontend:a,showIf:o}=n,s=v(n,ut);try{if(s.getError=X(s.getError),typeof o==`string`&&(n.showIf=o=X(o)),o&&!o(t))return}catch(e){}s.helperText&&(s.helperText=z(s.helperText,{html:!1}));let c=Z[r];if(t===!1&&r===`date_time`&&(s.$type=`dateTime`),c===B){let{fields:e}=s;typeof e==`string`&&(e=X(e)),s.valuesForAdd=re(I(e,!1),e=>e.defaultValue),s.details!=null||(s.details=!1),s.fields=t=>q.default.map(Y(I(e,t),t),(e,t)=>e&&m(m({k:t},e),{},{defaultValue:void 0})).filter(Boolean)}return i!==void 0&&r===`boolean`&&(s.placeholder=`Default value is ${JSON.stringify(i)}`),m({k:e,comp:c},s)})}function X(e){return(0,eval)(e)}var Z={string:y,number:Ce,boolean:be,select:C,multiselect:T,array:B,real_path:qe,vfs_path:c,username:pt,color:mt,show_html:({html:e})=>(0,V.createElement)(oe,{},String(e)),date_time:a,net_mask:ee};Z.showHtml=Z.show_html;function pt(e){let{value:t,onChange:n,multiple:r,groups:i}=e,a=v(e,dt),{data:o,element:s,loading:c}=pe(`get_accounts`),l=(0,V.useMemo)(()=>o&&q.default.sortBy(o.list,[e=>!e.isGroup,e=>!e.adminActualAccess,`username`]),[o]);return(!c||!o)&&s||(0,V.createElement)(r?T:C,m({value:t,onChange:n,options:l==null?void 0:l.filter(e=>i===void 0||i===e.isGroup).map(e=>({value:e.username,label:e.username,a:e})),renderOption:e=>{if(!e.a)return(0,V.createElement)(`span`,{style:{textDecoration:`line-through`}},e.label);let t=e.a.isGroup&&(0,V.createElement)(Le)||e.a.adminActualAccess&&D(Ne,`Can login into Admin`);return t?(0,V.createElement)(`span`,{},(0,V.createElement)(`span`,{style:{marginLeft:-8,marginRight:8}},t),e.label):e.label}},a))}function mt(e){return(0,V.createElement)(y,m({inputProps:m({type:`color`,style:{marginRight:24}},!e.value&&{value:`#888888`,style:{zIndex:1,opacity:.1}}),InputProps:{endAdornment:e.value?(0,V.createElement)(R,{icon:He,size:`small`,sx:{position:`absolute`,right:0,bottom:3},title:`Clear`,onClick(t){e.onChange(null,{was:e.value,event:t})}}):(0,V.createElement)(b,{sx:{position:`absolute`,width:`100%`,bottom:2,pt:`3px`,textAlign:`center`,color:`#fff`,background:`repeating-linear-gradient(45deg, #333, #333 10px, #444 10px, #444 20px)`}},`default`)},typing:!0},e))}p();function Q({updates:e}){let{list:t,error:n,setList:a,initializing:o}=L(e?`get_plugin_updates`:`get_plugins`,{},{map(e){e.config&&(e.config=fe(e.config,e=>X(`()=>(`+e+`)`)()))}}),[s,c]=(0,V.useState)(0);(0,V.useEffect)(()=>{a(e=>q.default.sortBy(e,e=>{var t;return(e.error?0:e.started?1:e.badApi?2:3)+_e(((t=e.repo)==null?void 0:t.split(`/`).reverse().join(`/`))||e.id).toLowerCase()}))},[t.length,s]);let l=`small`,{pause:d,pauseButton:p}=ne(`plugins`,()=>ht(E.suspend_plugins).then(e=>!e),{onClick(){return g(function*(){yield k(`set_config`,{values:{[E.suspend_plugins]:!d}}),d&&(yield ve(2e3),c(Date.now()))})()}}),ee=xe();return(0,V.createElement)(i,{error:se(n)?F(n,N):q.default.map(n,(e,t)=>`Error ${t} for: ${e.join(`, `)}`).join(`; `),rows:t.length?t:[],fillFlex:!0,initializing:o,disableColumnSelector:!0,quickFilter:!e,actionsHeader:!e&&p,getRowHeight:e&&(({model:e})=>e.changelog?`auto`:50),noRows:e&&`No updates available. Only plugins available on "search online" are checked.`,columns:[{field:`id`,headerName:`name`,flex:.3,minWidth:150,renderCell:O,valueGetter(e,t){return t.repo||t.id},mergeRender:{[e?`changelog`:`description`]:{sx:{fontSize:`x-small`}}}},{field:`version`,width:70,hideUnder:`sm`,cellInnerProps:{className:he},mergeRender:{installedVersion:{sx:{fontSize:`x-small`}}}},_t,m(m({},gt),{},{flex:1,hideUnder:`sm`}),{field:`installedVersion`,hideUnder:!0,dialogHidden:!0,renderCell:({value:e})=>e&&`Yours ${e}`},{field:`changelog`,headerName:`Change log`,flex:2,hideUnder:!e||`sm`,sx:{flexDirection:`column`,alignItems:`flex-start`},renderCell({value:e,row:t}){return Array.isArray(e)?(0,V.createElement)(Qe,{sx:{td:{p:0}}},(0,V.createElement)(it,{},q.default.uniq(q.default.sortBy(e,`version`).filter(e=>q.default.isString(e.message)&&e.message&&e.version>t.installedVersion)).map((e,t)=>(0,V.createElement)(lt,{key:t},(0,V.createElement)(r,{sx:{whiteSpace:`pre`,verticalAlign:`top`}},`• ${e.version}: `),(0,V.createElement)(r,{},z(e.message,{html:!1})))))):null}}],actions:({row:t,id:n})=>e?[(0,V.createElement)(f,{icon:ze,title:t.downloading?`Downloading`:t.updated?`Already updated`:`Update`,disabled:t.updated,progress:t.downloading,size:l,onClick(){return g(function*(){yield k(`update_plugin`,{id:n},{timeout:!1}).catch(e=>{var t;throw e.code===424?Error(`Failed dependencies: `+((t=e.cause)==null?void 0:t.map(e=>u(`plugin "`,e.id||e.repo,`" `)+e.error).join(`; `))):e}),h(`Plugin updated`)})()}})]:[(0,V.createElement)(f,t.started?{icon:Ie,title:(0,V.createElement)(b,{"aria-hidden":!0},`Stop ${n}`,(0,V.createElement)(`br`),`Started `+new Date(t.started).toLocaleString()),"aria-label":`Stop ${n}`,size:l,color:`success`,doneAnimation:!0,onClick:()=>k(`stop_plugin`,{id:n})}:{icon:ge,title:`Start ${n}`,disabled:d&&`All plugins are paused – Click the Resume button below`,size:l,onClick:()=>ke(n)}),(0,V.createElement)(f,{icon:t.config||!t.started||!t.log?Te:Ve,title:t.config||!t.log?`Options`:`Log`,size:l,disabled:!t.started&&`Start plugin to access options`||!t.config&&!t.log&&`No options and no log for this plugin`,onClick(){var e;let n=t.configDialog,r=ee.breakpoints.values[n==null?void 0:n.maxWidth]||(n==null||(e=n.sx)==null?void 0:e.maxWidth)||F(n==null?void 0:n.maxWidth,{xs:0})||432;return typeof r==`number`&&(r+=`px`),ft(t,r)}}),(0,V.createElement)(f,{icon:Ue,title:`Uninstall`,size:l,onClick(){return g(function*(){let e=yield ce(`${n}: delete configuration too?`,{trueText:`Yes`,falseText:`No`,after:({onClick:e})=>(0,V.createElement)(R,{variant:`outlined`,onClick(){e(void 0)}},`Abort`)});e!==void 0&&(yield k(`uninstall_plugin`,{id:n,deleteConfig:e}),h(`Plugin uninstalled`))})()}})]})}function ht(e){return k(`get_config`,{only:[e]}).then(t=>t[e])}var gt={field:`description`,mergeRender:{isTheme:{}},mergeRenderSx:{float:`left`}},_t={field:`isTheme`,headerName:`is theme`,hideUnder:!0,dialogHidden:!0,type:`boolean`,renderCell({value:e}){return e&&D(We,q.default.isString(e)?`${e} theme`:`theme`,{fontSize:`1.2rem`,mr:`.3em`})}};p();function vt(){let[e,t]=(0,V.useState)(``),{list:n,error:r,initializing:a}=L(`get_online_plugins`,{text:we(e,1e3)}),o=Se();return(0,V.createElement)(V.Fragment,{},(0,V.createElement)(y,{value:e,onChange:t,start:(0,V.createElement)(Fe),typing:!0,label:`Search text`}),(0,V.createElement)(i,{error:r&&Me(F(r,N)),rows:n.length?n:[],noRows:`No compatible plugins have been found`,fillFlex:!0,initializing:a,columnVisibilityModel:o.onlinePluginsColumns,onColumnVisibilityModelChange:e=>Oe.onlinePluginsColumns=e,columns:[{field:`id`,headerName:`name`,flex:1,renderCell:O,mergeRender:{description:{sx:{fontSize:`x-small`}}}},{field:`version`,width:70},{field:`pushed_at`,headerName:`last update`,valueGetter:e=>new Date(e).toLocaleDateString()},{field:`license`,width:80},_t,m(m({},gt),{},{flex:3,hideUnder:`sm`}),{field:`stargazers_count`,width:50,headerName:`stars`,align:`center`,hideUnder:`sm`}],actions:({row:e,id:t})=>[(0,V.createElement)(f,{icon:Pe,title:`Install`,progress:e.downloading,disabled:e.installed&&`Already installed`,tooltipProps:{placement:`bottom-end`},onClick:()=>Ee(e)}),(0,V.createElement)(f,{icon:Re,disabled:!e.preview,onClick:()=>le({title:t,Content:()=>(0,V.createElement)(yt,{imgs:De(e.preview)})})})]}))}function yt({imgs:e}){let[t,n]=(0,V.useState)(0);return(0,V.createElement)(_,{vert:!0,flex:1},(0,V.createElement)(_,{vert:!0,center:!0,height:0,flex:`auto`,minHeight:`50vh`,minWidth:`50vw`},(0,V.createElement)(`img`,{src:e[t],style:{margin:`auto`,maxWidth:`100%`,maxHeight:`100%`}})),e.length>1&&(0,V.createElement)(_,{center:!0},(0,V.createElement)(f,{icon:Be,disabled:!t,onClick:()=>n(t-1)}),(0,V.createElement)(f,{icon:Ge,disabled:t>=e.length-1,onClick:()=>n(t+1)})))}var $=[{label:`Installed`,path:`installed`,Pane:Q},{label:`Get more`,path:`get`,Pane:vt},{label:`Check updates`,path:`updates`,Pane:()=>(0,V.createElement)(Q,{updates:!0})}],bt=$.map(e=>e.path);function xt(){let[e,t]=Ke(`plugins`,bt),{Pane:n}=$[e];return(0,V.createElement)(V.Fragment,{},(0,V.createElement)(s,{value:e,onChange(e,n){t(n)}},$.map(e=>(0,V.createElement)(o,{key:e.path,label:e.label}))),(0,V.createElement)(n))}export{xt as default};