querysub 0.692.0 → 0.694.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "querysub",
3
- "version": "0.692.0",
3
+ "version": "0.694.0",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "note1": "note on node-forge fork, see https://github.com/digitalbazaar/forge/issues/744 for details",
@@ -27,6 +27,8 @@ const LATENCY_SAMPLE_LIMIT = 20;
27
27
  const LATENCY_HISTORY_LIMIT = 100;
28
28
  // Forget nodes we haven't been able to reach for this long.
29
29
  const NODE_EXPIRY_TIME = LATENCY_POLL_INTERVAL * 5;
30
+ // Each of the first pings to a node replaces the history instead of adding to it, so only the last of them survives into the real history.
31
+ const LATENCY_WARMUP_PINGS = 3;
30
32
 
31
33
  export type NodeLatencyInfo = {
32
34
  averageLatency: number;
@@ -70,15 +72,19 @@ export function getOwnLatencies(): { [nodeId: string]: number } {
70
72
 
71
73
  function recordLatency(nodeId: string, latency: number) {
72
74
  let prev = latencyByNode.get(nodeId);
73
- let sampleCount = Math.min(prev?.sampleCount || 0, LATENCY_SAMPLE_LIMIT);
75
+ let pingCount = prev?.sampleCount || 0;
74
76
  let history = prev?.history || [];
75
- history.push(latency);
76
- if (history.length > LATENCY_HISTORY_LIMIT) {
77
- history.shift();
77
+ if (pingCount < LATENCY_WARMUP_PINGS) {
78
+ history = [latency];
79
+ } else {
80
+ history.push(latency);
81
+ if (history.length > LATENCY_HISTORY_LIMIT) {
82
+ history.shift();
83
+ }
78
84
  }
79
85
  latencyByNode.set(nodeId, {
80
- averageLatency: ((prev?.averageLatency || 0) * sampleCount + latency) / (sampleCount + 1),
81
- sampleCount: sampleCount + 1,
86
+ averageLatency: history.reduce((sum, x) => sum + x, 0) / history.length,
87
+ sampleCount: pingCount + 1,
82
88
  lastSeen: Date.now(),
83
89
  history,
84
90
  });
@@ -1075,6 +1075,11 @@ export class Querysub {
1075
1075
  if (isClient()) {
1076
1076
  throw new Error(`--client processes cannot host a service. Either stop passing --client and keep the process on the network and trusted, or stop calling hostServer and call Querysub.configRootDiscoveryLocation instead. You MUST provide configRootDiscoveryLocation a valid nodeId. Which means either you do server selection manually, or if you are developing, just point it to "127-0-0-1.${getDomain()}:your local port here"`);
1077
1077
  }
1078
+ // Hot reloading on public servers breaks things when we update (as the git pull triggers a hot reload), so... don't do that.
1079
+ if (!isPublic() || yargObj.hot) {
1080
+ watchFilesAndTriggerHotReloading();
1081
+ }
1082
+
1078
1083
  await getIdentityCAPromise(getDomain());
1079
1084
  let times: {
1080
1085
  name: string;
@@ -30,6 +30,11 @@ export type InputLabelProps = Omit<InputProps, "label" | "title"> & {
30
30
  fillWidth?: boolean | number;
31
31
  };
32
32
 
33
+ // A checkbox is a small square that reads as belonging to the words beside it, so it sits tight against
34
+ // its label; every other input is a box of its own and wants room between the two.
35
+ const LABEL_GAP = 8;
36
+ const CHECKBOX_LABEL_GAP = 2;
37
+
33
38
  function roundToDecimals(value: number, decimals: number) {
34
39
  return Math.round(value * 10 ** decimals) / 10 ** decimals;
35
40
  }
@@ -148,7 +153,7 @@ export class InputLabel extends qreact.Component<InputLabelProps> {
148
153
  }
149
154
  return (
150
155
  <label onClick={onClick} class={
151
- css.hbox(8).button.relative
156
+ css.hbox(props.checkbox ? CHECKBOX_LABEL_GAP : LABEL_GAP).button.relative
152
157
  + " trigger-hover "
153
158
  + props.outerClass
154
159
  + (props.flavor === "large" && css.fontSize(18, "soft"))
@@ -6,7 +6,7 @@ import { isNode, sha256Hash, timeInHour } from "socket-function/src/misc";
6
6
  import { registerAliveChecker } from "../2-proxy/garbageCollection";
7
7
  import { generateLoginEmail } from "./loginEmail";
8
8
  import { logErrors } from "../errors";
9
- import { PermissionsParameters } from "../3-path-functions/syncSchema";
9
+ import { PermissionsCallback, PermissionsParameters } from "../3-path-functions/syncSchema";
10
10
  import { sendEmail_postmark } from "../email_ims_notifications/postmark";
11
11
  import { isClient } from "../config2";
12
12
  import { getExternalIP } from "../misc/networking";
@@ -457,6 +457,17 @@ export function satisifiedUserType(currentType: UserType, minimumType: UserType)
457
457
  return currentType === minimumType || userTypeRanking[currentType] > userTypeRanking[minimumType];
458
458
  }
459
459
 
460
+ export function createWildcardUserPERMISSIONS(config: { wildcardIndex: number; allowSuperUser?: boolean; }): PermissionsCallback {
461
+ let check: PermissionsCallback = permissionsConfig => {
462
+ if (config.allowSuperUser && isSuperUserPERMISSIONS()) return true;
463
+ let userId = getUserIdAllowUndefined();
464
+ if (!userId) return false;
465
+ return permissionsConfig.pathWildcards[config.wildcardIndex] === userId;
466
+ };
467
+ check.callImmutable = true;
468
+ return check;
469
+ }
470
+
460
471
  export function createUserPERMISSIONS(userType: UserType) {
461
472
  return () => {
462
473
  let allowed = isCurrentUserType(userType);