Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb2e261c62 |
No files matched your search
@@ -1,20 +1,5 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
## 1.2.15 (2026-03-26)
|
|
||||||
|
|
||||||
- Fix critical RCE vulnerability in /api/ping endpoint (follow-up to
|
|
||||||
CVE-2021-46704). Credit: JuHwiSang.
|
|
||||||
|
|
||||||
- Fix device IDs containing special characters (e.g., %) not being handled
|
|
||||||
correctly in the UI due to a regression in Mithril 2.3.8.
|
|
||||||
|
|
||||||
## 1.2.14 (2026-03-12)
|
|
||||||
|
|
||||||
- Prevent UI crash when a malformed URL is sent to the server.
|
|
||||||
|
|
||||||
- Fix potential edge-case bugs in expression evaluation and session
|
|
||||||
serialization.
|
|
||||||
|
|
||||||
## 1.2.13 (2024-06-06)
|
## 1.2.13 (2024-06-06)
|
||||||
|
|
||||||
- Increase connection timeout for UI and NBI from 30 to 120 seconds to avoid
|
- Increase connection timeout for UI and NBI from 30 to 120 seconds to avoid
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ import { PermissionSet, Expression } from "../types.ts";
|
|||||||
import { evaluate, or } from "./expression/util.ts";
|
import { evaluate, or } from "./expression/util.ts";
|
||||||
|
|
||||||
export default class Authorizer {
|
export default class Authorizer {
|
||||||
declare private permissionSets: PermissionSet[];
|
private declare permissionSets: PermissionSet[];
|
||||||
declare private validatorCache: WeakMap<
|
private declare validatorCache: WeakMap<
|
||||||
any,
|
any,
|
||||||
(mutationType, mutation, any) => boolean
|
(mutationType, mutation, any) => boolean
|
||||||
>;
|
>;
|
||||||
declare private hasAccessCache: Map<string, boolean>;
|
private declare hasAccessCache: Map<string, boolean>;
|
||||||
declare private getFilterCache: Map<string, Expression>;
|
private declare getFilterCache: Map<string, Expression>;
|
||||||
|
|
||||||
public constructor(permissionSets: PermissionSet[]) {
|
public constructor(permissionSets: PermissionSet[]) {
|
||||||
this.permissionSets = permissionSets;
|
this.permissionSets = permissionSets;
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ const TWO = BI.BigInt(2);
|
|||||||
const NEGATIVE_ONE = BI.BigInt(-1);
|
const NEGATIVE_ONE = BI.BigInt(-1);
|
||||||
|
|
||||||
class Indeterminates {
|
class Indeterminates {
|
||||||
declare public map: Map<string, number>;
|
public declare map: Map<string, number>;
|
||||||
declare public sortedKeys: string[];
|
public declare sortedKeys: string[];
|
||||||
|
|
||||||
public constructor(str?: string) {
|
public constructor(str?: string) {
|
||||||
this.map = new Map();
|
this.map = new Map();
|
||||||
@@ -98,7 +98,7 @@ function findGcd(a: BI.bigint, b: BI.bigint): BI.bigint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Polynomial {
|
class Polynomial {
|
||||||
declare public terms: Term[];
|
public declare terms: Term[];
|
||||||
|
|
||||||
public constructor(terms: Term[]) {
|
public constructor(terms: Term[]) {
|
||||||
this.terms = terms;
|
this.terms = terms;
|
||||||
|
|||||||
@@ -955,7 +955,7 @@ export function covers(expr1: Expression, expr2: Expression): boolean {
|
|||||||
expr2 = normalize(expr2);
|
expr2 = normalize(expr2);
|
||||||
if (!expr2) return true;
|
if (!expr2) return true;
|
||||||
expr1 = normalize(expr1);
|
expr1 = normalize(expr1);
|
||||||
if (!Array.isArray(expr1) && expr1) return true;
|
if (!Array.isArray(expr1)) return !!expr1;
|
||||||
|
|
||||||
const synt1 = Clause.fromExpression(expr1);
|
const synt1 = Clause.fromExpression(expr1);
|
||||||
const synt2 = Clause.fromExpression(expr2);
|
const synt2 = Clause.fromExpression(expr2);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import Path from "./path.ts";
|
import Path from "./path.ts";
|
||||||
|
|
||||||
export default class PathSet {
|
export default class PathSet {
|
||||||
declare private lengthIndex: Set<Path>[];
|
private declare lengthIndex: Set<Path>[];
|
||||||
declare private fragmentIndex: Map<string, Set<Path>>[];
|
private declare fragmentIndex: Map<string, Set<Path>>[];
|
||||||
declare private stringIndex: Map<string, Path>;
|
private declare stringIndex: Map<string, Path>;
|
||||||
|
|
||||||
public constructor() {
|
public constructor() {
|
||||||
this.lengthIndex = [];
|
this.lengthIndex = [];
|
||||||
|
|||||||
+5
-5
@@ -30,11 +30,11 @@ function legalChar(c: number): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class Path {
|
export default class Path {
|
||||||
declare public readonly segments: Segments;
|
public declare readonly segments: Segments;
|
||||||
declare public readonly wildcard: number;
|
public declare readonly wildcard: number;
|
||||||
declare public readonly alias: number;
|
public declare readonly alias: number;
|
||||||
declare protected _string: string;
|
protected declare _string: string;
|
||||||
declare protected _stringIndex: number[];
|
protected declare _stringIndex: number[];
|
||||||
|
|
||||||
protected static parseAliasValue(
|
protected static parseAliasValue(
|
||||||
pattern: string,
|
pattern: string,
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ interface Instance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class InstanceSet {
|
export default class InstanceSet {
|
||||||
declare private set: Set<Instance>;
|
private declare set: Set<Instance>;
|
||||||
|
|
||||||
public constructor() {
|
public constructor() {
|
||||||
this.set = new Set();
|
this.set = new Set();
|
||||||
|
|||||||
+7
-16
@@ -1,6 +1,6 @@
|
|||||||
import { platform } from "node:os";
|
import { platform } from "node:os";
|
||||||
import { execFile } from "node:child_process";
|
import { exec } from "node:child_process";
|
||||||
import { domainToASCII, domainToUnicode } from "node:url";
|
import { domainToASCII } from "node:url";
|
||||||
|
|
||||||
export interface PingResult {
|
export interface PingResult {
|
||||||
packetsTransmitted: number;
|
packetsTransmitted: number;
|
||||||
@@ -16,16 +16,9 @@ function isValidHost(host: string): boolean {
|
|||||||
// Valid chars in IPv4, IPv6, domain names
|
// Valid chars in IPv4, IPv6, domain names
|
||||||
if (/^[a-zA-Z0-9\-.:[\]-]+$/.test(host)) return true;
|
if (/^[a-zA-Z0-9\-.:[\]-]+$/.test(host)) return true;
|
||||||
|
|
||||||
const lowercase = host.toLowerCase();
|
|
||||||
const ascii = domainToASCII(lowercase);
|
|
||||||
|
|
||||||
// Check if input is an IDN convert to Punycode
|
// Check if input is an IDN convert to Punycode
|
||||||
// Can't merge with above because domainToASCII doesn't accept IP addresses
|
// Can't merge with above because domainToASCII doesn't accept IP addresses
|
||||||
if (!/^[a-zA-Z0-9\-.:[\]-]+$/.test(ascii)) return false;
|
return /^[a-zA-Z0-9\-.:[\]-]+$/.test(domainToASCII(host));
|
||||||
|
|
||||||
// Round-trip to ensure the original host matches its normalized form.
|
|
||||||
// This prevents bypasses where domainToASCII strips paths (e.g. "example.com/;cmd").
|
|
||||||
return lowercase === domainToUnicode(ascii);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parsePing(osPlatform: string, stdout: string): PingResult {
|
export function parsePing(osPlatform: string, stdout: string): PingResult {
|
||||||
@@ -80,26 +73,24 @@ export function ping(
|
|||||||
): void {
|
): void {
|
||||||
// Validate input to prevent possible remote code execution
|
// Validate input to prevent possible remote code execution
|
||||||
// Credit to Alex Hordijk for reporting this vulnerability
|
// Credit to Alex Hordijk for reporting this vulnerability
|
||||||
// Credit to JuHwiSang for reporting a follow-up vulnerability
|
|
||||||
if (!isValidHost(host)) return callback(new Error("Invalid host"));
|
if (!isValidHost(host)) return callback(new Error("Invalid host"));
|
||||||
host = host.replace("[", "").replace("]", "");
|
host = host.replace("[", "").replace("]", "");
|
||||||
let args: string[];
|
let cmd: string;
|
||||||
|
|
||||||
switch (platform()) {
|
switch (platform()) {
|
||||||
case "linux":
|
case "linux":
|
||||||
args = ["-w", "1", "-i", "0.2", "-c", "3", "--", host];
|
cmd = `ping -w 1 -i 0.2 -c 3 ${host}`;
|
||||||
break;
|
break;
|
||||||
case "freebsd":
|
case "freebsd":
|
||||||
// Send a single packet because on FreeBSD only superuser can send
|
// Send a single packet because on FreeBSD only superuser can send
|
||||||
// packets that are only 200 ms apart.
|
// packets that are only 200 ms apart.
|
||||||
args = ["-t", "1", "-c", "3", "--", host];
|
cmd = `ping -t 1 -c 3 ${host}`;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return callback(new Error("Platform not supported"));
|
return callback(new Error("Platform not supported"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use execFile instead of exec to avoid shell interpretation of the host
|
exec(cmd, (err, stdout) => {
|
||||||
execFile("ping", args, (err, stdout) => {
|
|
||||||
if (err) return callback(err);
|
if (err) return callback(err);
|
||||||
const parsed: PingResult = parsePing(platform(), stdout);
|
const parsed: PingResult = parsePing(platform(), stdout);
|
||||||
return callback(err, parsed, stdout);
|
return callback(err, parsed, stdout);
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ interface Revisions<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class VersionedMap<K, V> {
|
export default class VersionedMap<K, V> {
|
||||||
declare private _sizeDiff: number[];
|
private declare _sizeDiff: number[];
|
||||||
declare private _revision: number;
|
private declare _revision: number;
|
||||||
declare private map: Map<K, (V | symbol)[]>;
|
private declare map: Map<K, (V | symbol)[]>;
|
||||||
declare public dirty: number;
|
public declare dirty: number;
|
||||||
|
|
||||||
public constructor() {
|
public constructor() {
|
||||||
this._sizeDiff = [0];
|
this._sizeDiff = [0];
|
||||||
@@ -112,8 +112,6 @@ export default class VersionedMap<K, V> {
|
|||||||
prev = v;
|
prev = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev === NONEXISTENT && !res.delete) return null;
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,8 +122,6 @@ export default class VersionedMap<K, V> {
|
|||||||
del,
|
del,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!mutations) return;
|
|
||||||
|
|
||||||
const revisions = [];
|
const revisions = [];
|
||||||
|
|
||||||
let prev: V | symbol = NONEXISTENT;
|
let prev: V | symbol = NONEXISTENT;
|
||||||
@@ -153,7 +149,7 @@ export default class VersionedMap<K, V> {
|
|||||||
|
|
||||||
public *diff(): IterableIterator<[K, V, V]> {
|
public *diff(): IterableIterator<[K, V, V]> {
|
||||||
for (const [key, revisions] of this.map) {
|
for (const [key, revisions] of this.map) {
|
||||||
if (revisions.length <= 1) continue;
|
if (revisions.length === 1) continue;
|
||||||
let first = revisions[0];
|
let first = revisions[0];
|
||||||
let last = revisions[revisions.length - 1];
|
let last = revisions[revisions.length - 1];
|
||||||
if (first === NONEXISTENT && last === NONEXISTENT) continue;
|
if (first === NONEXISTENT && last === NONEXISTENT) continue;
|
||||||
|
|||||||
Generated
+2719
-2895
File diff suppressed because it is too large.
Load diff
+24
-24
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "genieacs",
|
"name": "genieacs",
|
||||||
"version": "1.2.15",
|
"version": "1.2.13",
|
||||||
"description": "A TR-069 Auto Configuration Server (ACS)",
|
"description": "A TR-069 Auto Configuration Server (ACS)",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -26,15 +26,15 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@breejs/later": "^4.2.0",
|
"@breejs/later": "^4.2.0",
|
||||||
"@koa/bodyparser": "^5.1.2",
|
"@koa/bodyparser": "^5.1.1",
|
||||||
"@koa/router": "^13.1.1",
|
"@koa/router": "^13.1.0",
|
||||||
"bson": "^4.7.2",
|
"bson": "^4.7.2",
|
||||||
"espresso-iisojs": "^1.0.8",
|
"espresso-iisojs": "^1.0.8",
|
||||||
"iconv-lite": "^0.6.3",
|
"iconv-lite": "^0.6.3",
|
||||||
"ipaddr.js": "^2.3.0",
|
"ipaddr.js": "^2.2.0",
|
||||||
"jsonwebtoken": "^9.0.3",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"koa": "^2.16.4",
|
"koa": "^2.15.3",
|
||||||
"koa-compress": "^5.2.1",
|
"koa-compress": "^5.1.0",
|
||||||
"koa-jwt": "^4.0.3",
|
"koa-jwt": "^4.0.3",
|
||||||
"koa-send": "^5.0.1",
|
"koa-send": "^5.0.1",
|
||||||
"mongodb": "^4.16.0",
|
"mongodb": "^4.16.0",
|
||||||
@@ -42,26 +42,26 @@
|
|||||||
"seedrandom": "^3.0.5"
|
"seedrandom": "^3.0.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/codemirror": "^5.60.17",
|
"@types/codemirror": "^5.60.15",
|
||||||
"@types/jsonwebtoken": "^9.0.10",
|
"@types/jsonwebtoken": "^9.0.6",
|
||||||
"@types/koa": "^2.15.0",
|
"@types/koa": "^2.15.0",
|
||||||
"@types/koa-compress": "^4.0.7",
|
"@types/koa-compress": "^4.0.6",
|
||||||
"@types/mithril": "^2.2.8",
|
"@types/mithril": "^2.2.6",
|
||||||
"@types/node": "^20.19.37",
|
"@types/node": "^20.14.2",
|
||||||
"@types/parsimmon": "^1.10.9",
|
"@types/parsimmon": "^1.10.9",
|
||||||
"@types/seedrandom": "^3.0.8",
|
"@types/seedrandom": "^3.0.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
"@typescript-eslint/eslint-plugin": "^7.12.0",
|
||||||
"@typescript-eslint/parser": "^7.18.0",
|
"@typescript-eslint/parser": "^7.12.0",
|
||||||
"codemirror": "^5.65.21",
|
"codemirror": "^5.65.16",
|
||||||
"esbuild": "^0.27.4",
|
"esbuild": "^0.25.0",
|
||||||
"eslint": "^8.57.1",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-prettier": "^9.1.2",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"mithril": "^2.3.8",
|
"mithril": "^2.2.2",
|
||||||
"prettier": "^3.8.1",
|
"prettier": "^3.3.1",
|
||||||
"sql.js": "^1.14.1",
|
"sql.js": "^1.10.3",
|
||||||
"svgo": "^3.3.3",
|
"svgo": "^3.3.2",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.4.5",
|
||||||
"yaml": "^1.10.3"
|
"yaml": "^1.10.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12.13.0"
|
"node": ">=12.13.0"
|
||||||
|
|||||||
+1
-35
@@ -1,7 +1,7 @@
|
|||||||
import test from "node:test";
|
import test from "node:test";
|
||||||
import assert from "node:assert";
|
import assert from "node:assert";
|
||||||
import initSqlJs from "sql.js/dist/sql-asm.js";
|
import initSqlJs from "sql.js/dist/sql-asm.js";
|
||||||
import { covers, minimize, unionDiff } from "../lib/common/expression/synth.ts";
|
import { minimize, unionDiff } from "../lib/common/expression/synth.ts";
|
||||||
import { parse, stringify } from "../lib/common/expression/parser.ts";
|
import { parse, stringify } from "../lib/common/expression/parser.ts";
|
||||||
|
|
||||||
const STRING_VALUES = [null, "", "a", "ab", "ab10", "ab-10"];
|
const STRING_VALUES = [null, "", "a", "ab", "ab10", "ab-10"];
|
||||||
@@ -115,37 +115,3 @@ void test("unionDiff", async () => {
|
|||||||
assert.strictEqual(setsEqual(res4, diffSet), true);
|
assert.strictEqual(setsEqual(res4, diffSet), true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
void test("covers", async () => {
|
|
||||||
assert.strictEqual(covers(false, false), true);
|
|
||||||
assert.strictEqual(covers(false, parse("decimal > 5 AND decimal < 3")), true);
|
|
||||||
assert.strictEqual(covers(parse("true"), parse("decimal > 0")), true);
|
|
||||||
assert.strictEqual(covers(parse("true"), parse("false")), true);
|
|
||||||
assert.strictEqual(covers(parse("false"), parse("false")), true);
|
|
||||||
assert.strictEqual(covers(parse("false"), parse("decimal > 0")), false);
|
|
||||||
assert.strictEqual(covers(parse("decimal >= 0"), parse("decimal > 0")), true);
|
|
||||||
assert.strictEqual(
|
|
||||||
covers(parse("decimal > 0"), parse("decimal >= 0")),
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
const cases = [
|
|
||||||
["decimal >= 0", "decimal > 0"],
|
|
||||||
["decimal > 0", "decimal > 5"],
|
|
||||||
["string IS NOT NULL", "string = 'a'"],
|
|
||||||
["true", "decimal > 0"],
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const [c1, c2] of cases) {
|
|
||||||
const res1 = await query(c1);
|
|
||||||
const res2 = await query(c2);
|
|
||||||
const coversResult = covers(parse(c1), parse(c2));
|
|
||||||
const actuallyCovers = Array.from(res2).every((r) => res1.has(r));
|
|
||||||
|
|
||||||
assert.strictEqual(
|
|
||||||
coversResult,
|
|
||||||
actuallyCovers,
|
|
||||||
`covers(${c1}, ${c2}) should match actual coverage`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
+1
-2
@@ -11,8 +11,7 @@
|
|||||||
"strictFunctionTypes": true,
|
"strictFunctionTypes": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"allowImportingTsExtensions": true,
|
"allowImportingTsExtensions": true
|
||||||
"skipLibCheck": true
|
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"./bin/*.ts",
|
"./bin/*.ts",
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ type AutocompleteCallback = (
|
|||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
export default class Autocomplete {
|
export default class Autocomplete {
|
||||||
declare private callback: AutocompleteCallback;
|
private declare callback: AutocompleteCallback;
|
||||||
declare private element: HTMLInputElement;
|
private declare element: HTMLInputElement;
|
||||||
declare private hideTimeout: NodeJS.Timeout;
|
private declare hideTimeout: NodeJS.Timeout;
|
||||||
declare private visible: boolean;
|
private declare visible: boolean;
|
||||||
declare private default: string;
|
private declare default: string;
|
||||||
declare private selection: number;
|
private declare selection: number;
|
||||||
declare private container: HTMLElement;
|
private declare container: HTMLElement;
|
||||||
|
|
||||||
public constructor(className: string, callback: AutocompleteCallback) {
|
public constructor(className: string, callback: AutocompleteCallback) {
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ export function structureConfig(config: Config[]): any {
|
|||||||
if (idx >= 0 && idx < MAX_ARRAY_SIZE && String(idx) === key) {
|
if (idx >= 0 && idx < MAX_ARRAY_SIZE && String(idx) === key) {
|
||||||
const pos = Math.floor(idx / MAX_BITS);
|
const pos = Math.floor(idx / MAX_BITS);
|
||||||
if (!indexes[pos]) indexes[pos] = 0;
|
if (!indexes[pos]) indexes[pos] = 0;
|
||||||
indexes[pos] |= 1 << (idx % MAX_BITS);
|
indexes[pos] |= 1 << idx % MAX_BITS;
|
||||||
} else {
|
} else {
|
||||||
indexes = [];
|
indexes = [];
|
||||||
break;
|
break;
|
||||||
|
|||||||
+2
-29
@@ -3,29 +3,6 @@ import { m } from "./components.ts";
|
|||||||
import config from "./config.ts";
|
import config from "./config.ts";
|
||||||
import * as store from "./store.ts";
|
import * as store from "./store.ts";
|
||||||
|
|
||||||
// Workaround for Mithril 2.3.8 regression
|
|
||||||
// https://github.com/MithrilJS/mithril.js/issues/3064
|
|
||||||
function getPathParamFromHash(hash: string, prefix: string): string | null {
|
|
||||||
if (!hash.startsWith(prefix)) return null;
|
|
||||||
|
|
||||||
const pathWithQuery = hash.slice(prefix.length);
|
|
||||||
|
|
||||||
// Stop at query string or hash fragment (mirrors Mithril's parsePathname)
|
|
||||||
const queryIdx = pathWithQuery.indexOf("?");
|
|
||||||
const hashIdx = pathWithQuery.indexOf("#");
|
|
||||||
let pathEnd = pathWithQuery.length;
|
|
||||||
if (queryIdx >= 0) pathEnd = Math.min(pathEnd, queryIdx);
|
|
||||||
if (hashIdx >= 0) pathEnd = Math.min(pathEnd, hashIdx);
|
|
||||||
|
|
||||||
const rawPath = pathWithQuery.slice(0, pathEnd);
|
|
||||||
|
|
||||||
// Normalize: collapse slashes, remove trailing slash (matches Mithril)
|
|
||||||
const normalizedPath = rawPath.replace(/\/{2,}/g, "/").replace(/\/$/, "");
|
|
||||||
|
|
||||||
// Decode once (Mithril already decoded with decodeURIComponentSafe)
|
|
||||||
return decodeURIComponent(normalizedPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function init(
|
export function init(
|
||||||
args: Record<string, unknown>,
|
args: Record<string, unknown>,
|
||||||
): Promise<Record<string, unknown>> {
|
): Promise<Record<string, unknown>> {
|
||||||
@@ -35,13 +12,9 @@ export function init(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const deviceId =
|
|
||||||
getPathParamFromHash(window.location.hash, "#!/devices/") ??
|
|
||||||
(args.id as string);
|
|
||||||
|
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
deviceId: deviceId,
|
deviceId: args.id,
|
||||||
deviceFilter: ["=", ["PARAM", "DeviceID.ID"], deviceId],
|
deviceFilter: ["=", ["PARAM", "DeviceID.ID"], args.id],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user