Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions dashboard/note.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
```
<div
style="display:flex;flex-direction:row;gap:15px;"
>
<div>${"privilege:" + entry.privilege}</div>
<div>${"authMode:" + entry.authMode}</div>
<div>${"fabricIndex:" + entry.fabricIndex}</div>
</div>
<div>subjects:${JSON.stringify(entry.subjects)}</div>
<div>targets:${JSON.stringify(entry.targets)}</div>

```
15 changes: 15 additions & 0 deletions dashboard/src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,21 @@ export class MatterClient {
await this.sendCommand("update_node", 10, { node_id: nodeId, software_version: softwareVersion });
}

async setACLEntry(nodeId: number, entry: any) {
return await this.sendCommand("set_acl_entry", 0, {
node_id: nodeId,
entry: entry,
});
}

async setNodeBinding(nodeId: number, endpoint: number, bindings: any) {
return await this.sendCommand("set_node_binding", 0, {
node_id: nodeId,
endpoint: endpoint,
bindings: bindings,
});
}

async sendCommand<T extends keyof APICommands>(
command: T,
require_schema: number | undefined = undefined,
Expand Down
8 changes: 8 additions & 0 deletions dashboard/src/client/models/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ export interface APICommands {
requestArgs: {};
response: {};
};
set_acl_entry: {
requestArgs: {};
response: {};
};
set_node_binding: {
requestArgs: {};
response: {};
};
}

export interface CommandMessage {
Expand Down
109 changes: 109 additions & 0 deletions dashboard/src/components/dialogs/acl/model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@

export type AccessControlEntryRawInput = {
"1": number;
"2": number;
"3": number[];
"4": null;
"254": number;
};

export type AccessControlTargetStruct = {
cluster: number | undefined;
endpoint: number | undefined;
deviceType: number | undefined;
};

export type AccessControlEntryStruct = {
privilege: number;
authMode: number;
subjects: number[];
targets: AccessControlTargetStruct[] | undefined;
fabricIndex: number;
};

export class AccessControlTargetTransformer {
private static readonly KEY_MAPPING: {
[inputKey: string]: keyof AccessControlTargetStruct;
} = {
"0": "cluster",
"1": "endpoint",
"2": "deviceType",
};

public static transform(input: any): AccessControlTargetStruct {
if (!input || typeof input !== "object") {
throw new Error("Invalid input: expected an object");
}

const result: Partial<AccessControlTargetStruct> = {};
const keyMapping = AccessControlTargetTransformer.KEY_MAPPING;

for (const key in input) {
if (key in keyMapping) {
const mappedKey = keyMapping[key];
if (mappedKey) {
const value = input[key];
if (value === undefined) continue;
result[mappedKey] = value;
}
}
}
return result as AccessControlTargetStruct;
}
}

export class AccessControlEntryDataTransformer {
private static readonly KEY_MAPPING: {
[inputKey: string]: keyof AccessControlEntryStruct;
} = {
"1": "privilege",
"2": "authMode",
"3": "subjects",
"4": "targets",
"254": "fabricIndex",
};

public static transform(input: any): AccessControlEntryStruct {
if (!input || typeof input !== "object") {
throw new Error("Invalid input: expected an object");
}

const result: Partial<AccessControlEntryStruct> = {};
const keyMapping = AccessControlEntryDataTransformer.KEY_MAPPING;

for (const key in input) {
if (key in keyMapping) {
const mappedKey = keyMapping[key];
if (mappedKey) {
const value = input[key];
if (value === undefined) continue;
if (mappedKey === "subjects") {
result[mappedKey] = Array.isArray(value) ? value : undefined;
} else if (mappedKey === "targets") {
if (Array.isArray(value)) {
const _targets = Object.values(value).map((val) =>
AccessControlTargetTransformer.transform(val),
);
result[mappedKey] = _targets;
} else {
result[mappedKey] = undefined;
}
} else {
result[mappedKey] = value;
}
}
}
}

if (
result.privilege === undefined ||
result.authMode === undefined ||
result.subjects === undefined ||
result.fabricIndex === undefined
) {
throw new Error("Missing required fields in AccessControlEntryStruct");
}

return result as AccessControlEntryStruct;
}
}
61 changes: 61 additions & 0 deletions dashboard/src/components/dialogs/binding/model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
export type InputType = {
[key: string]: number | number[] | undefined;
};

export interface BindingEntryStruct {
node: number;
group: number | undefined;
endpoint: number;
cluster: number | undefined;
fabricIndex: number | undefined;
}

export class BindingEntryDataTransformer {
private static readonly KEY_MAPPING: {
[inputKey: string]: keyof BindingEntryStruct;
} = {
"1": "node",
"3": "endpoint",
"4": "cluster",
"254": "fabricIndex",
};

public static transform(input: any): BindingEntryStruct {
if (!input || typeof input !== "object") {
throw new Error("Invalid input: expected an object");
}

const result: Partial<BindingEntryStruct> = {};
const keyMapping = BindingEntryDataTransformer.KEY_MAPPING;

for (const key in input) {
if (key in keyMapping) {
const mappedKey = keyMapping[key];
if (mappedKey) {
const value = input[key];
if (value === undefined) {
continue;
}
if (mappedKey === "fabricIndex") {
result[mappedKey] = value === undefined ? undefined : Number(value);
} else if (mappedKey === "node" || mappedKey === "endpoint") {
result[mappedKey] = Number(value);
} else {
result[mappedKey] = value as BindingEntryStruct[typeof mappedKey];
}
}
}
}

// Validate required fields
if (
result.node === undefined ||
result.endpoint === undefined ||
result.fabricIndex === undefined
) {
throw new Error("Missing required fields in BindingEntryStruct");
}

return result as BindingEntryStruct;
}
}
Loading