@project-chip/matter.js 0.10.4 → 0.10.6
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/dist/cjs/device/LegacyInteractionServer.d.ts +1 -1
- package/dist/cjs/device/LegacyInteractionServer.d.ts.map +1 -1
- package/dist/cjs/device/LegacyInteractionServer.js +4 -2
- package/dist/cjs/device/LegacyInteractionServer.js.map +2 -2
- package/dist/cjs/node/server/TransactionalInteractionServer.d.ts +1 -1
- package/dist/cjs/node/server/TransactionalInteractionServer.d.ts.map +1 -1
- package/dist/cjs/node/server/TransactionalInteractionServer.js +6 -2
- package/dist/cjs/node/server/TransactionalInteractionServer.js.map +2 -2
- package/dist/cjs/protocol/interaction/AccessControlManager.d.ts.map +1 -1
- package/dist/cjs/protocol/interaction/AccessControlManager.js +6 -2
- package/dist/cjs/protocol/interaction/AccessControlManager.js.map +2 -2
- package/dist/cjs/protocol/interaction/InteractionServer.d.ts +1 -1
- package/dist/cjs/protocol/interaction/InteractionServer.d.ts.map +1 -1
- package/dist/cjs/protocol/interaction/InteractionServer.js +5 -4
- package/dist/cjs/protocol/interaction/InteractionServer.js.map +2 -2
- package/dist/cjs/protocol/interaction/SubscriptionHandler.d.ts +1 -1
- package/dist/cjs/protocol/interaction/SubscriptionHandler.d.ts.map +1 -1
- package/dist/cjs/protocol/interaction/SubscriptionHandler.js +1 -1
- package/dist/cjs/protocol/interaction/SubscriptionHandler.js.map +2 -2
- package/dist/cjs/session/SecureSession.d.ts.map +1 -1
- package/dist/cjs/session/SecureSession.js +2 -1
- package/dist/cjs/session/SecureSession.js.map +2 -2
- package/dist/cjs/session/case/CaseServer.d.ts.map +1 -1
- package/dist/cjs/session/case/CaseServer.js +6 -2
- package/dist/cjs/session/case/CaseServer.js.map +2 -2
- package/dist/esm/device/LegacyInteractionServer.d.ts +1 -1
- package/dist/esm/device/LegacyInteractionServer.d.ts.map +1 -1
- package/dist/esm/device/LegacyInteractionServer.js +4 -2
- package/dist/esm/device/LegacyInteractionServer.js.map +2 -2
- package/dist/esm/node/server/TransactionalInteractionServer.d.ts +1 -1
- package/dist/esm/node/server/TransactionalInteractionServer.d.ts.map +1 -1
- package/dist/esm/node/server/TransactionalInteractionServer.js +6 -2
- package/dist/esm/node/server/TransactionalInteractionServer.js.map +2 -2
- package/dist/esm/protocol/interaction/AccessControlManager.d.ts.map +1 -1
- package/dist/esm/protocol/interaction/AccessControlManager.js +6 -2
- package/dist/esm/protocol/interaction/AccessControlManager.js.map +2 -2
- package/dist/esm/protocol/interaction/InteractionServer.d.ts +1 -1
- package/dist/esm/protocol/interaction/InteractionServer.d.ts.map +1 -1
- package/dist/esm/protocol/interaction/InteractionServer.js +5 -4
- package/dist/esm/protocol/interaction/InteractionServer.js.map +2 -2
- package/dist/esm/protocol/interaction/SubscriptionHandler.d.ts +1 -1
- package/dist/esm/protocol/interaction/SubscriptionHandler.d.ts.map +1 -1
- package/dist/esm/protocol/interaction/SubscriptionHandler.js +1 -1
- package/dist/esm/protocol/interaction/SubscriptionHandler.js.map +2 -2
- package/dist/esm/session/SecureSession.d.ts.map +1 -1
- package/dist/esm/session/SecureSession.js +2 -1
- package/dist/esm/session/SecureSession.js.map +2 -2
- package/dist/esm/session/case/CaseServer.d.ts.map +1 -1
- package/dist/esm/session/case/CaseServer.js +6 -2
- package/dist/esm/session/case/CaseServer.js.map +2 -2
- package/package.json +3 -3
- package/src/device/LegacyInteractionServer.ts +5 -1
- package/src/node/server/TransactionalInteractionServer.ts +9 -1
- package/src/protocol/interaction/AccessControlManager.ts +5 -1
- package/src/protocol/interaction/InteractionServer.ts +4 -2
- package/src/protocol/interaction/SubscriptionHandler.ts +8 -4
- package/src/session/SecureSession.ts +1 -0
- package/src/session/case/CaseServer.ts +4 -0
|
@@ -21,7 +21,7 @@ import { TypeFromSchema } from "../tlv/TlvSchema.js";
|
|
|
21
21
|
export declare class LegacyInteractionServer extends InteractionServer {
|
|
22
22
|
#private;
|
|
23
23
|
constructor(config: InteractionServer.Configuration);
|
|
24
|
-
protected readAttribute(path: AttributePath, attribute: AnyAttributeServer<any>, exchange: MessageExchange<MatterDevice>, isFabricFiltered: boolean, message: Message, endpoint: EndpointInterface): Promise<{
|
|
24
|
+
protected readAttribute(path: AttributePath, attribute: AnyAttributeServer<any>, exchange: MessageExchange<MatterDevice>, isFabricFiltered: boolean, message: Message, endpoint: EndpointInterface, offline?: boolean): Promise<{
|
|
25
25
|
version: number;
|
|
26
26
|
value: any;
|
|
27
27
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LegacyInteractionServer.d.ts","sourceRoot":"","sources":["../../../src/device/LegacyInteractionServer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAA+B,MAAM,sCAAsC,CAAC;AACxH,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAGnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAGrE,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAE3E,OAAO,EAAE,cAAc,EAAE,MAAM,gDAAgD,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,8CAA8C,CAAC;AAGxH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAKrD;;;GAGG;AACH,qBAAa,uBAAwB,SAAQ,iBAAiB;;gBAI9C,MAAM,EAAE,iBAAiB,CAAC,aAAa;cA+C1B,aAAa,CAClC,IAAI,EAAE,aAAa,EACnB,SAAS,EAAE,kBAAkB,CAAC,GAAG,CAAC,EAClC,QAAQ,EAAE,eAAe,CAAC,YAAY,CAAC,EACvC,gBAAgB,EAAE,OAAO,EACzB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,iBAAiB;;;;
|
|
1
|
+
{"version":3,"file":"LegacyInteractionServer.d.ts","sourceRoot":"","sources":["../../../src/device/LegacyInteractionServer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAA+B,MAAM,sCAAsC,CAAC;AACxH,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAGnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAGrE,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAE3E,OAAO,EAAE,cAAc,EAAE,MAAM,gDAAgD,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,8CAA8C,CAAC;AAGxH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAKrD;;;GAGG;AACH,qBAAa,uBAAwB,SAAQ,iBAAiB;;gBAI9C,MAAM,EAAE,iBAAiB,CAAC,aAAa;cA+C1B,aAAa,CAClC,IAAI,EAAE,aAAa,EACnB,SAAS,EAAE,kBAAkB,CAAC,GAAG,CAAC,EAClC,QAAQ,EAAE,eAAe,CAAC,YAAY,CAAC,EACvC,gBAAgB,EAAE,OAAO,EACzB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,UAAQ;;;;cAoBM,SAAS,CAC9B,IAAI,EAAE,SAAS,EACf,YAAY,EAAE,cAAc,CAAC,OAAO,cAAc,CAAC,EAAE,GAAG,SAAS,EACjE,KAAK,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,EAC/B,QAAQ,EAAE,eAAe,CAAC,YAAY,CAAC,EACvC,gBAAgB,EAAE,OAAO,EACzB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,iBAAiB,GAC5B,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;cAKV,cAAc,CACnC,IAAI,EAAE,aAAa,EACnB,SAAS,EAAE,eAAe,CAAC,GAAG,CAAC,EAC/B,KAAK,EAAE,GAAG,EACV,QAAQ,EAAE,eAAe,CAAC,YAAY,CAAC,EACvC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,iBAAiB,EAC3B,8BAA8B,CAAC,EAAE,OAAO,EACxC,WAAW,CAAC,EAAE,OAAO;cAeA,aAAa,CAClC,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,EAChC,QAAQ,EAAE,eAAe,CAAC,YAAY,CAAC,EACvC,aAAa,EAAE,GAAG,EAClB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,iBAAiB,EAC3B,8BAA8B,UAAQ;;;;;;CAa7C"}
|
|
@@ -76,8 +76,10 @@ class LegacyInteractionServer extends import_InteractionServer.InteractionServer
|
|
|
76
76
|
);
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
-
async readAttribute(path, attribute, exchange, isFabricFiltered, message, endpoint) {
|
|
80
|
-
|
|
79
|
+
async readAttribute(path, attribute, exchange, isFabricFiltered, message, endpoint, offline = false) {
|
|
80
|
+
if (!offline) {
|
|
81
|
+
this.#assertAccess(path, exchange, attribute.readAcl);
|
|
82
|
+
}
|
|
81
83
|
const data = await super.readAttribute(path, attribute, exchange, isFabricFiltered, message, endpoint);
|
|
82
84
|
if (attribute instanceof import_AttributeServer.FabricScopedAttributeServer && !isFabricFiltered) {
|
|
83
85
|
const { value, version } = data;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/device/LegacyInteractionServer.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { MatterDevice } from \"../MatterDevice.js\";\nimport { AccessLevel } from \"../cluster/Cluster.js\";\nimport { AccessControlCluster } from \"../cluster/definitions/index.js\";\nimport { AnyAttributeServer, AttributeServer, FabricScopedAttributeServer } from \"../cluster/server/AttributeServer.js\";\nimport { CommandServer } from \"../cluster/server/CommandServer.js\";\nimport { AnyEventServer } from \"../cluster/server/EventServer.js\";\nimport { Message } from \"../codec/MessageCodec.js\";\nimport { InternalError } from \"../common/MatterError.js\";\nimport { EndpointNumber } from \"../datatype/EndpointNumber.js\";\nimport { EndpointInterface } from \"../endpoint/EndpointInterface.js\";\nimport { Diagnostic } from \"../log/Diagnostic.js\";\nimport { Logger } from \"../log/Logger.js\";\nimport { MessageExchange } from \"../protocol/MessageExchange.js\";\nimport { AccessControlManager, AccessDeniedError } from \"../protocol/interaction/AccessControlManager.js\";\nimport { EventStorageData } from \"../protocol/interaction/EventHandler.js\";\nimport { InteractionEndpointStructure } from \"../protocol/interaction/InteractionEndpointStructure.js\";\nimport { TlvEventFilter } from \"../protocol/interaction/InteractionProtocol.js\";\nimport { AttributePath, CommandPath, EventPath, InteractionServer } from \"../protocol/interaction/InteractionServer.js\";\nimport { SecureSession } from \"../session/SecureSession.js\";\nimport { Session } from \"../session/Session.js\";\nimport { TypeFromSchema } from \"../tlv/TlvSchema.js\";\nimport { Endpoint } from \"./Endpoint.js\";\n\nconst logger = Logger.get(\"LegacyInteractionServer\");\n\n/**\n * Interactionserver for the legacy API code paths which includes ACL checks before calling the actual\n * attribute/command handlers.\n */\nexport class LegacyInteractionServer extends InteractionServer {\n #endpointStructure: InteractionEndpointStructure;\n #aclManager?: AccessControlManager;\n\n constructor(config: InteractionServer.Configuration) {\n const { endpointStructure } = config;\n super(config);\n this.#endpointStructure = endpointStructure;\n }\n\n #getAclManager(session: Session<MatterDevice>) {\n if (this.#aclManager !== undefined) {\n return this.#aclManager;\n }\n const rootEndpoint = this.#endpointStructure.getEndpoint(EndpointNumber(0)) as Endpoint;\n if (rootEndpoint === undefined) {\n throw new InternalError(\"Root endpoint must exist.\");\n }\n const aclCluster = rootEndpoint.getClusterServer(AccessControlCluster);\n if (aclCluster === undefined) {\n throw new InternalError(\"Access control cluster must exist on root endpoint.\");\n }\n const aclManager = (this.#aclManager = new AccessControlManager(aclCluster.attributes.acl.get(session, false)));\n aclCluster.subscribeAclAttribute(() => {\n const completeVal = aclCluster.attributes.acl.get(session, false);\n logger.info(\"ACL updated\", completeVal);\n aclManager.updateAccessControlList(completeVal);\n });\n return aclManager;\n }\n\n #assertAccess(\n path: AttributePath | EventPath | CommandPath,\n exchange: MessageExchange<MatterDevice>,\n desiredAccessLevel: AccessLevel,\n ) {\n const { endpointId, clusterId } = path;\n const endpoint = this.#endpointStructure.getEndpoint(endpointId);\n if (endpoint === undefined) {\n throw new InternalError(\"Endpoint not found for ACL check. This should never happen.\");\n }\n const aclManager = this.#getAclManager(exchange.session);\n if (\n !aclManager.allowsPrivilege(exchange.session as SecureSession<any>, endpoint, clusterId, desiredAccessLevel)\n ) {\n throw new AccessDeniedError(\n `Access to ${endpointId}/${Diagnostic.hex(clusterId)} denied on ${exchange.session.name}.`,\n );\n }\n }\n\n protected override async readAttribute(\n path: AttributePath,\n attribute: AnyAttributeServer<any>,\n exchange: MessageExchange<MatterDevice>,\n isFabricFiltered: boolean,\n message: Message,\n endpoint: EndpointInterface,\n ) {\n this.#assertAccess(path, exchange, attribute.readAcl);\n const data = await super.readAttribute(path, attribute, exchange, isFabricFiltered, message, endpoint);\n if (attribute instanceof FabricScopedAttributeServer && !isFabricFiltered) {\n const { value, version } = data;\n return {\n value: attribute.sanitizeFabricSensitiveFields(\n value,\n (exchange.session as SecureSession<MatterDevice>).fabric,\n ),\n version,\n };\n }\n return data;\n }\n\n protected override async readEvent(\n path: EventPath,\n eventFilters: TypeFromSchema<typeof TlvEventFilter>[] | undefined,\n event: AnyEventServer<any, any>,\n exchange: MessageExchange<MatterDevice>,\n isFabricFiltered: boolean,\n message: Message,\n endpoint: EndpointInterface,\n ): Promise<EventStorageData<any>[]> {\n this.#assertAccess(path, exchange, event.readAcl);\n return super.readEvent(path, eventFilters, event, exchange, isFabricFiltered, message, endpoint);\n }\n\n protected override async writeAttribute(\n path: AttributePath,\n attribute: AttributeServer<any>,\n value: any,\n exchange: MessageExchange<MatterDevice>,\n message: Message,\n endpoint: EndpointInterface,\n receivedWithinTimedInteraction?: boolean,\n isListWrite?: boolean,\n ) {\n this.#assertAccess(path, exchange, attribute.writeAcl);\n return super.writeAttribute(\n path,\n attribute,\n value,\n exchange,\n message,\n endpoint,\n receivedWithinTimedInteraction,\n isListWrite,\n );\n }\n\n protected override async invokeCommand(\n path: CommandPath,\n command: CommandServer<any, any>,\n exchange: MessageExchange<MatterDevice>,\n commandFields: any,\n message: Message,\n endpoint: EndpointInterface,\n receivedWithinTimedInteraction = false,\n ) {\n this.#assertAccess(path, exchange, command.invokeAcl);\n return super.invokeCommand(\n path,\n command,\n exchange,\n commandFields,\n message,\n endpoint,\n receivedWithinTimedInteraction,\n );\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,yBAAqC;AACrC,6BAAiF;AAIjF,yBAA8B;AAC9B,4BAA+B;AAE/B,wBAA2B;AAC3B,oBAAuB;AAEvB,kCAAwD;AAIxD,+BAAyE;AAvBzE;AAAA;AAAA;AAAA;AAAA;AA6BA,MAAM,SAAS,qBAAO,IAAI,yBAAyB;AAM5C,MAAM,gCAAgC,2CAAkB;AAAA,EAC3D;AAAA,EACA;AAAA,EAEA,YAAY,QAAyC;AACjD,UAAM,EAAE,kBAAkB,IAAI;AAC9B,UAAM,MAAM;AACZ,SAAK,qBAAqB;AAAA,EAC9B;AAAA,EAEA,eAAe,SAAgC;AAC3C,QAAI,KAAK,gBAAgB,QAAW;AAChC,aAAO,KAAK;AAAA,IAChB;AACA,UAAM,eAAe,KAAK,mBAAmB,gBAAY,sCAAe,CAAC,CAAC;AAC1E,QAAI,iBAAiB,QAAW;AAC5B,YAAM,IAAI,iCAAc,2BAA2B;AAAA,IACvD;AACA,UAAM,aAAa,aAAa,iBAAiB,uCAAoB;AACrE,QAAI,eAAe,QAAW;AAC1B,YAAM,IAAI,iCAAc,qDAAqD;AAAA,IACjF;AACA,UAAM,aAAc,KAAK,cAAc,IAAI,iDAAqB,WAAW,WAAW,IAAI,IAAI,SAAS,KAAK,CAAC;AAC7G,eAAW,sBAAsB,MAAM;AACnC,YAAM,cAAc,WAAW,WAAW,IAAI,IAAI,SAAS,KAAK;AAChE,aAAO,KAAK,eAAe,WAAW;AACtC,iBAAW,wBAAwB,WAAW;AAAA,IAClD,CAAC;AACD,WAAO;AAAA,EACX;AAAA,EAEA,cACI,MACA,UACA,oBACF;AACE,UAAM,EAAE,YAAY,UAAU,IAAI;AAClC,UAAM,WAAW,KAAK,mBAAmB,YAAY,UAAU;AAC/D,QAAI,aAAa,QAAW;AACxB,YAAM,IAAI,iCAAc,6DAA6D;AAAA,IACzF;AACA,UAAM,aAAa,KAAK,eAAe,SAAS,OAAO;AACvD,QACI,CAAC,WAAW,gBAAgB,SAAS,SAA+B,UAAU,WAAW,kBAAkB,GAC7G;AACE,YAAM,IAAI;AAAA,QACN,aAAa,UAAU,IAAI,6BAAW,IAAI,SAAS,CAAC,cAAc,SAAS,QAAQ,IAAI;AAAA,MAC3F;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAyB,cACrB,MACA,WACA,UACA,kBACA,SACA,
|
|
4
|
+
"sourcesContent": ["/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { MatterDevice } from \"../MatterDevice.js\";\nimport { AccessLevel } from \"../cluster/Cluster.js\";\nimport { AccessControlCluster } from \"../cluster/definitions/index.js\";\nimport { AnyAttributeServer, AttributeServer, FabricScopedAttributeServer } from \"../cluster/server/AttributeServer.js\";\nimport { CommandServer } from \"../cluster/server/CommandServer.js\";\nimport { AnyEventServer } from \"../cluster/server/EventServer.js\";\nimport { Message } from \"../codec/MessageCodec.js\";\nimport { InternalError } from \"../common/MatterError.js\";\nimport { EndpointNumber } from \"../datatype/EndpointNumber.js\";\nimport { EndpointInterface } from \"../endpoint/EndpointInterface.js\";\nimport { Diagnostic } from \"../log/Diagnostic.js\";\nimport { Logger } from \"../log/Logger.js\";\nimport { MessageExchange } from \"../protocol/MessageExchange.js\";\nimport { AccessControlManager, AccessDeniedError } from \"../protocol/interaction/AccessControlManager.js\";\nimport { EventStorageData } from \"../protocol/interaction/EventHandler.js\";\nimport { InteractionEndpointStructure } from \"../protocol/interaction/InteractionEndpointStructure.js\";\nimport { TlvEventFilter } from \"../protocol/interaction/InteractionProtocol.js\";\nimport { AttributePath, CommandPath, EventPath, InteractionServer } from \"../protocol/interaction/InteractionServer.js\";\nimport { SecureSession } from \"../session/SecureSession.js\";\nimport { Session } from \"../session/Session.js\";\nimport { TypeFromSchema } from \"../tlv/TlvSchema.js\";\nimport { Endpoint } from \"./Endpoint.js\";\n\nconst logger = Logger.get(\"LegacyInteractionServer\");\n\n/**\n * Interactionserver for the legacy API code paths which includes ACL checks before calling the actual\n * attribute/command handlers.\n */\nexport class LegacyInteractionServer extends InteractionServer {\n #endpointStructure: InteractionEndpointStructure;\n #aclManager?: AccessControlManager;\n\n constructor(config: InteractionServer.Configuration) {\n const { endpointStructure } = config;\n super(config);\n this.#endpointStructure = endpointStructure;\n }\n\n #getAclManager(session: Session<MatterDevice>) {\n if (this.#aclManager !== undefined) {\n return this.#aclManager;\n }\n const rootEndpoint = this.#endpointStructure.getEndpoint(EndpointNumber(0)) as Endpoint;\n if (rootEndpoint === undefined) {\n throw new InternalError(\"Root endpoint must exist.\");\n }\n const aclCluster = rootEndpoint.getClusterServer(AccessControlCluster);\n if (aclCluster === undefined) {\n throw new InternalError(\"Access control cluster must exist on root endpoint.\");\n }\n const aclManager = (this.#aclManager = new AccessControlManager(aclCluster.attributes.acl.get(session, false)));\n aclCluster.subscribeAclAttribute(() => {\n const completeVal = aclCluster.attributes.acl.get(session, false);\n logger.info(\"ACL updated\", completeVal);\n aclManager.updateAccessControlList(completeVal);\n });\n return aclManager;\n }\n\n #assertAccess(\n path: AttributePath | EventPath | CommandPath,\n exchange: MessageExchange<MatterDevice>,\n desiredAccessLevel: AccessLevel,\n ) {\n const { endpointId, clusterId } = path;\n const endpoint = this.#endpointStructure.getEndpoint(endpointId);\n if (endpoint === undefined) {\n throw new InternalError(\"Endpoint not found for ACL check. This should never happen.\");\n }\n const aclManager = this.#getAclManager(exchange.session);\n if (\n !aclManager.allowsPrivilege(exchange.session as SecureSession<any>, endpoint, clusterId, desiredAccessLevel)\n ) {\n throw new AccessDeniedError(\n `Access to ${endpointId}/${Diagnostic.hex(clusterId)} denied on ${exchange.session.name}.`,\n );\n }\n }\n\n protected override async readAttribute(\n path: AttributePath,\n attribute: AnyAttributeServer<any>,\n exchange: MessageExchange<MatterDevice>,\n isFabricFiltered: boolean,\n message: Message,\n endpoint: EndpointInterface,\n offline = false,\n ) {\n // Offline read do not require ACL checks\n if (!offline) {\n this.#assertAccess(path, exchange, attribute.readAcl);\n }\n const data = await super.readAttribute(path, attribute, exchange, isFabricFiltered, message, endpoint);\n if (attribute instanceof FabricScopedAttributeServer && !isFabricFiltered) {\n const { value, version } = data;\n return {\n value: attribute.sanitizeFabricSensitiveFields(\n value,\n (exchange.session as SecureSession<MatterDevice>).fabric,\n ),\n version,\n };\n }\n return data;\n }\n\n protected override async readEvent(\n path: EventPath,\n eventFilters: TypeFromSchema<typeof TlvEventFilter>[] | undefined,\n event: AnyEventServer<any, any>,\n exchange: MessageExchange<MatterDevice>,\n isFabricFiltered: boolean,\n message: Message,\n endpoint: EndpointInterface,\n ): Promise<EventStorageData<any>[]> {\n this.#assertAccess(path, exchange, event.readAcl);\n return super.readEvent(path, eventFilters, event, exchange, isFabricFiltered, message, endpoint);\n }\n\n protected override async writeAttribute(\n path: AttributePath,\n attribute: AttributeServer<any>,\n value: any,\n exchange: MessageExchange<MatterDevice>,\n message: Message,\n endpoint: EndpointInterface,\n receivedWithinTimedInteraction?: boolean,\n isListWrite?: boolean,\n ) {\n this.#assertAccess(path, exchange, attribute.writeAcl);\n return super.writeAttribute(\n path,\n attribute,\n value,\n exchange,\n message,\n endpoint,\n receivedWithinTimedInteraction,\n isListWrite,\n );\n }\n\n protected override async invokeCommand(\n path: CommandPath,\n command: CommandServer<any, any>,\n exchange: MessageExchange<MatterDevice>,\n commandFields: any,\n message: Message,\n endpoint: EndpointInterface,\n receivedWithinTimedInteraction = false,\n ) {\n this.#assertAccess(path, exchange, command.invokeAcl);\n return super.invokeCommand(\n path,\n command,\n exchange,\n commandFields,\n message,\n endpoint,\n receivedWithinTimedInteraction,\n );\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -38,7 +38,7 @@ export declare class TransactionalInteractionServer extends InteractionServer {
|
|
|
38
38
|
blockNewActivity(): void;
|
|
39
39
|
onNewExchange(exchange: MessageExchange<MatterDevice>): Promise<void>;
|
|
40
40
|
get aclServer(): AccessControlServer;
|
|
41
|
-
protected readAttribute(path: AttributePath, attribute: AnyAttributeServer<any>, exchange: MessageExchange<MatterDevice>, fabricFiltered: boolean, message: Message, endpoint: EndpointInterface): Promise<{
|
|
41
|
+
protected readAttribute(path: AttributePath, attribute: AnyAttributeServer<any>, exchange: MessageExchange<MatterDevice>, fabricFiltered: boolean, message: Message, endpoint: EndpointInterface, offline?: boolean): Promise<{
|
|
42
42
|
version: number;
|
|
43
43
|
value: any;
|
|
44
44
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransactionalInteractionServer.d.ts","sourceRoot":"","sources":["../../../../src/node/server/TransactionalInteractionServer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"TransactionalInteractionServer.d.ts","sourceRoot":"","sources":["../../../../src/node/server/TransactionalInteractionServer.ts"],"names":[],"mappings":"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"}
|
|
@@ -68,6 +68,7 @@ __export(TransactionalInteractionServer_exports, {
|
|
|
68
68
|
module.exports = __toCommonJS(TransactionalInteractionServer_exports);
|
|
69
69
|
var import_ActionTracer = require("../../behavior/context/ActionTracer.js");
|
|
70
70
|
var import_NodeActivity = require("../../behavior/context/NodeActivity.js");
|
|
71
|
+
var import_OfflineContext = require("../../behavior/context/server/OfflineContext.js");
|
|
71
72
|
var import_OnlineContext = require("../../behavior/context/server/OnlineContext.js");
|
|
72
73
|
var import_AccessControlServer = require("../../behavior/definitions/access-control/AccessControlServer.js");
|
|
73
74
|
var import_BasicInformationServer = require("../../behavior/definitions/basic-information/BasicInformationServer.js");
|
|
@@ -160,8 +161,11 @@ class TransactionalInteractionServer extends import_InteractionServer.Interactio
|
|
|
160
161
|
}
|
|
161
162
|
return this.#aclServer = aclServer;
|
|
162
163
|
}
|
|
163
|
-
async readAttribute(path, attribute, exchange, fabricFiltered, message, endpoint) {
|
|
164
|
-
const readAttribute = () => super.readAttribute(path, attribute, exchange, fabricFiltered, message, endpoint);
|
|
164
|
+
async readAttribute(path, attribute, exchange, fabricFiltered, message, endpoint, offline = false) {
|
|
165
|
+
const readAttribute = () => super.readAttribute(path, attribute, exchange, fabricFiltered, message, endpoint, offline);
|
|
166
|
+
if (offline) {
|
|
167
|
+
return import_OfflineContext.OfflineContext.act("offline-read", this.#activity, readAttribute);
|
|
168
|
+
}
|
|
165
169
|
return (0, import_OnlineContext.OnlineContext)({
|
|
166
170
|
activity: exchange[activityKey],
|
|
167
171
|
fabricFiltered,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/node/server/TransactionalInteractionServer.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { MatterDevice } from \"../../MatterDevice.js\";\nimport { AccessControl } from \"../../behavior/AccessControl.js\";\nimport { ActionContext } from \"../../behavior/context/ActionContext.js\";\nimport { ActionTracer } from \"../../behavior/context/ActionTracer.js\";\nimport { NodeActivity } from \"../../behavior/context/NodeActivity.js\";\nimport { OnlineContext } from \"../../behavior/context/server/OnlineContext.js\";\nimport { AccessControlServer } from \"../../behavior/definitions/access-control/AccessControlServer.js\";\nimport { BasicInformationServer } from \"../../behavior/definitions/basic-information/BasicInformationServer.js\";\nimport { AccessControlCluster } from \"../../cluster/definitions/AccessControlCluster.js\";\nimport { AnyAttributeServer, AttributeServer } from \"../../cluster/server/AttributeServer.js\";\nimport { CommandServer } from \"../../cluster/server/CommandServer.js\";\nimport { AnyEventServer } from \"../../cluster/server/EventServer.js\";\nimport { Message } from \"../../codec/MessageCodec.js\";\nimport { InternalError } from \"../../common/MatterError.js\";\nimport { Endpoint } from \"../../endpoint/Endpoint.js\";\nimport { EndpointInterface } from \"../../endpoint/EndpointInterface.js\";\nimport { EndpointServer } from \"../../endpoint/EndpointServer.js\";\nimport { EndpointLifecycle } from \"../../endpoint/properties/EndpointLifecycle.js\";\nimport { Diagnostic } from \"../../log/Diagnostic.js\";\nimport { MessageExchange } from \"../../protocol/MessageExchange.js\";\nimport { AccessDeniedError } from \"../../protocol/interaction/AccessControlManager.js\";\nimport { EventStorageData } from \"../../protocol/interaction/EventHandler.js\";\nimport { InteractionEndpointStructure } from \"../../protocol/interaction/InteractionEndpointStructure.js\";\nimport {\n InteractionServerMessenger,\n WriteRequest,\n WriteResponse,\n} from \"../../protocol/interaction/InteractionMessenger.js\";\nimport { TlvEventFilter } from \"../../protocol/interaction/InteractionProtocol.js\";\nimport {\n AttributePath,\n CommandPath,\n EventPath,\n InteractionServer,\n} from \"../../protocol/interaction/InteractionServer.js\";\nimport { TypeFromSchema } from \"../../tlv/TlvSchema.js\";\nimport { MaybePromise } from \"../../util/Promises.js\";\nimport { ServerNode } from \"../ServerNode.js\";\n\nconst activityKey = Symbol(\"activity\");\n\ninterface WithActivity {\n [activityKey]?: NodeActivity.Activity;\n}\n\nconst AclClusterId = AccessControlCluster.id;\nconst AclAttributeId = AccessControlCluster.attributes.acl.id;\n\n/**\n * Wire up an InteractionServer that initializes an InvocationContext earlier than the cluster API supports.\n *\n * This is necessary for attributes because the ClusterServer attribute APIs are synchronous while transaction\n * management is asynchronous.\n *\n * It's not necessary for command handling because that API is entirely async. We do it here, however, just for the\n * sake of consistency.\n *\n * This could be integrated directly into InteractionServer but this further refactoring is probably warranted there\n * regardless. This keeps the touch light for now.\n */\nexport class TransactionalInteractionServer extends InteractionServer {\n #endpointStructure: InteractionEndpointStructure;\n #changeListener: (type: EndpointLifecycle.Change) => void;\n #endpoint: Endpoint<ServerNode.RootEndpoint>;\n #activity: NodeActivity;\n #newActivityBlocked = false;\n #aclServer?: AccessControlServer;\n #aclUpdateIsDelayed = false;\n\n static async create(endpoint: Endpoint<ServerNode.RootEndpoint>) {\n const endpointStructure = new InteractionEndpointStructure();\n\n const maxPathsPerInvoke = await endpoint.act(\n agent => agent.get(BasicInformationServer).state.maxPathsPerInvoke,\n );\n\n return new TransactionalInteractionServer(endpoint, {\n endpointStructure,\n subscriptionOptions: endpoint.state.network.subscriptionOptions,\n maxPathsPerInvoke,\n });\n }\n\n constructor(endpoint: Endpoint<ServerNode.RootEndpoint>, config: InteractionServer.Configuration) {\n super(config);\n\n const { endpointStructure } = config;\n\n this.#activity = endpoint.env.get(NodeActivity);\n\n this.#endpoint = endpoint;\n this.#endpointStructure = endpointStructure;\n\n // TODO - rewrite element lookup so we don't need to build the secondary endpoint structure cache\n this.#updateStructure();\n this.#changeListener = type => {\n switch (type) {\n case EndpointLifecycle.Change.PartsReady:\n case EndpointLifecycle.Change.ClientsChanged:\n case EndpointLifecycle.Change.ServersChanged:\n case EndpointLifecycle.Change.Destroyed:\n this.#updateStructure();\n break;\n }\n };\n\n endpoint.lifecycle.changed.on(this.#changeListener);\n }\n\n async [Symbol.asyncDispose]() {\n this.#endpoint.lifecycle.changed.off(this.#changeListener);\n await this.close();\n this.#endpointStructure.close();\n }\n\n blockNewActivity() {\n this.#newActivityBlocked = true;\n }\n\n override async onNewExchange(exchange: MessageExchange<MatterDevice>) {\n // When closing, ignore anything newly incoming\n if (this.#newActivityBlocked || this.isClosing) {\n return;\n }\n\n // Activity tracking. This provides diagnostic information and prevents the server from shutting down whilst\n // the exchange is active\n using activity = this.#activity.begin(`session#${exchange.session.id.toString(16)}`);\n (exchange as WithActivity)[activityKey] = activity;\n\n // Delegate to InteractionServerMessenger\n return new InteractionServerMessenger(exchange)\n .handleRequest(this)\n .finally(() => delete (exchange as WithActivity)[activityKey]);\n }\n\n get aclServer() {\n if (this.#aclServer !== undefined) {\n return this.#aclServer;\n }\n const aclServer = this.#endpoint.act(agent => agent.get(AccessControlServer));\n if (MaybePromise.is(aclServer)) {\n throw new InternalError(\"AccessControlServer should already be initialized.\");\n }\n return (this.#aclServer = aclServer);\n }\n\n protected override async readAttribute(\n path: AttributePath,\n attribute: AnyAttributeServer<any>,\n exchange: MessageExchange<MatterDevice>,\n fabricFiltered: boolean,\n message: Message,\n endpoint: EndpointInterface,\n ) {\n const readAttribute = () => super.readAttribute(path, attribute, exchange, fabricFiltered, message, endpoint);\n\n return OnlineContext({\n activity: (exchange as WithActivity)[activityKey],\n fabricFiltered,\n message,\n exchange,\n tracer: this.#tracer,\n actionType: ActionTracer.ActionType.Read,\n endpoint,\n root: this.#endpoint,\n }).act(readAttribute);\n }\n\n protected override async readEvent(\n path: EventPath,\n eventFilters: TypeFromSchema<typeof TlvEventFilter>[] | undefined,\n event: AnyEventServer<any, any>,\n exchange: MessageExchange<MatterDevice>,\n fabricFiltered: boolean,\n message: Message,\n endpoint: EndpointInterface,\n ): Promise<EventStorageData<any>[]> {\n const readEvent = (context: ActionContext) => {\n if (!context.authorizedFor(event.readAcl, { cluster: path.clusterId } as AccessControl.Location)) {\n throw new AccessDeniedError(\n `Access to ${endpoint.number}/${Diagnostic.hex(path.clusterId)} denied on ${exchange.session.name}.`,\n );\n }\n return super.readEvent(path, eventFilters, event, exchange, fabricFiltered, message, endpoint);\n };\n\n return OnlineContext({\n activity: (exchange as WithActivity)[activityKey],\n fabricFiltered,\n message,\n exchange,\n tracer: this.#tracer,\n actionType: ActionTracer.ActionType.Read,\n endpoint,\n root: this.#endpoint,\n }).act(readEvent);\n }\n\n override async handleWriteRequest(\n exchange: MessageExchange<MatterDevice>,\n writeRequest: WriteRequest,\n message: Message,\n ): Promise<WriteResponse> {\n const result = await super.handleWriteRequest(exchange, writeRequest, message);\n\n // We delayed the ACL update during the write transaction, so we need to update it now that anything is written\n if (this.#aclUpdateIsDelayed) {\n this.aclServer.aclUpdateDelayed = false;\n this.#aclUpdateIsDelayed = false;\n }\n return result;\n }\n\n protected override async writeAttribute(\n path: AttributePath,\n attribute: AttributeServer<any>,\n value: any,\n exchange: MessageExchange<MatterDevice>,\n message: Message,\n endpoint: EndpointInterface,\n timed = false,\n isListWrite?: boolean,\n ) {\n const writeAttribute = () =>\n super.writeAttribute(path, attribute, value, exchange, message, endpoint, timed, isListWrite);\n\n if (path.endpointId === 0 && path.clusterId === AclClusterId && path.attributeId === AclAttributeId) {\n // This is a hack to prevent the ACL from updating while we are in the middle of a write transaction\n // and is needed because Acl should not become effective during writing of the ACL itself.\n this.aclServer.aclUpdateDelayed = true;\n this.#aclUpdateIsDelayed = true;\n } else if (this.#aclUpdateIsDelayed) {\n // Ok it seems that acl was written, but we now write another path, so we can update Acl attribute now\n this.aclServer.aclUpdateDelayed = false;\n this.#aclUpdateIsDelayed = false;\n }\n\n return OnlineContext({\n activity: (exchange as WithActivity)[activityKey],\n timed,\n message,\n exchange,\n fabricFiltered: true,\n tracer: this.#tracer,\n actionType: ActionTracer.ActionType.Write,\n endpoint,\n root: this.#endpoint,\n }).act(writeAttribute);\n }\n\n protected override async invokeCommand(\n path: CommandPath,\n command: CommandServer<any, any>,\n exchange: MessageExchange<MatterDevice>,\n commandFields: any,\n message: Message,\n endpoint: EndpointInterface,\n timed = false,\n ) {\n const invokeCommand = (context: ActionContext) => {\n if (!context.authorizedFor(command.invokeAcl, { cluster: path.clusterId } as AccessControl.Location)) {\n throw new AccessDeniedError(\n `Access to ${endpoint.number}/${Diagnostic.hex(path.clusterId)} denied on ${exchange.session.name}.`,\n );\n }\n return super.invokeCommand(path, command, exchange, commandFields, message, endpoint, timed);\n };\n\n return OnlineContext({\n activity: (exchange as WithActivity)[activityKey],\n command: true,\n timed,\n message,\n exchange,\n tracer: this.#tracer,\n actionType: ActionTracer.ActionType.Invoke,\n endpoint,\n root: this.#endpoint,\n }).act(invokeCommand);\n }\n\n get #tracer() {\n if (this.#endpoint.env.has(ActionTracer)) {\n return this.#endpoint.env.get(ActionTracer);\n }\n }\n\n #updateStructure() {\n if (this.#endpoint.lifecycle.isPartsReady) {\n this.#endpointStructure.initializeFromEndpoint(EndpointServer.forEndpoint(this.#endpoint));\n }\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,0BAA6B;AAC7B,0BAA6B;AAC7B,2BAA8B;AAC9B,iCAAoC;AACpC,oCAAuC;AACvC,kCAAqC;AAKrC,yBAA8B;AAG9B,4BAA+B;AAC/B,+BAAkC;AAClC,wBAA2B;AAE3B,kCAAkC;AAElC,0CAA6C;AAC7C,kCAIO;AAEP,+BAKO;AAEP,sBAA6B;
|
|
4
|
+
"sourcesContent": ["/**\n * @license\n * Copyright 2022-2024 Matter.js Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { MatterDevice } from \"../../MatterDevice.js\";\nimport { AccessControl } from \"../../behavior/AccessControl.js\";\nimport { ActionContext } from \"../../behavior/context/ActionContext.js\";\nimport { ActionTracer } from \"../../behavior/context/ActionTracer.js\";\nimport { NodeActivity } from \"../../behavior/context/NodeActivity.js\";\nimport { OfflineContext } from \"../../behavior/context/server/OfflineContext.js\";\nimport { OnlineContext } from \"../../behavior/context/server/OnlineContext.js\";\nimport { AccessControlServer } from \"../../behavior/definitions/access-control/AccessControlServer.js\";\nimport { BasicInformationServer } from \"../../behavior/definitions/basic-information/BasicInformationServer.js\";\nimport { AccessControlCluster } from \"../../cluster/definitions/AccessControlCluster.js\";\nimport { AnyAttributeServer, AttributeServer } from \"../../cluster/server/AttributeServer.js\";\nimport { CommandServer } from \"../../cluster/server/CommandServer.js\";\nimport { AnyEventServer } from \"../../cluster/server/EventServer.js\";\nimport { Message } from \"../../codec/MessageCodec.js\";\nimport { InternalError } from \"../../common/MatterError.js\";\nimport { Endpoint } from \"../../endpoint/Endpoint.js\";\nimport { EndpointInterface } from \"../../endpoint/EndpointInterface.js\";\nimport { EndpointServer } from \"../../endpoint/EndpointServer.js\";\nimport { EndpointLifecycle } from \"../../endpoint/properties/EndpointLifecycle.js\";\nimport { Diagnostic } from \"../../log/Diagnostic.js\";\nimport { MessageExchange } from \"../../protocol/MessageExchange.js\";\nimport { AccessDeniedError } from \"../../protocol/interaction/AccessControlManager.js\";\nimport { EventStorageData } from \"../../protocol/interaction/EventHandler.js\";\nimport { InteractionEndpointStructure } from \"../../protocol/interaction/InteractionEndpointStructure.js\";\nimport {\n InteractionServerMessenger,\n WriteRequest,\n WriteResponse,\n} from \"../../protocol/interaction/InteractionMessenger.js\";\nimport { TlvEventFilter } from \"../../protocol/interaction/InteractionProtocol.js\";\nimport {\n AttributePath,\n CommandPath,\n EventPath,\n InteractionServer,\n} from \"../../protocol/interaction/InteractionServer.js\";\nimport { TypeFromSchema } from \"../../tlv/TlvSchema.js\";\nimport { MaybePromise } from \"../../util/Promises.js\";\nimport { ServerNode } from \"../ServerNode.js\";\n\nconst activityKey = Symbol(\"activity\");\n\ninterface WithActivity {\n [activityKey]?: NodeActivity.Activity;\n}\n\nconst AclClusterId = AccessControlCluster.id;\nconst AclAttributeId = AccessControlCluster.attributes.acl.id;\n\n/**\n * Wire up an InteractionServer that initializes an InvocationContext earlier than the cluster API supports.\n *\n * This is necessary for attributes because the ClusterServer attribute APIs are synchronous while transaction\n * management is asynchronous.\n *\n * It's not necessary for command handling because that API is entirely async. We do it here, however, just for the\n * sake of consistency.\n *\n * This could be integrated directly into InteractionServer but this further refactoring is probably warranted there\n * regardless. This keeps the touch light for now.\n */\nexport class TransactionalInteractionServer extends InteractionServer {\n #endpointStructure: InteractionEndpointStructure;\n #changeListener: (type: EndpointLifecycle.Change) => void;\n #endpoint: Endpoint<ServerNode.RootEndpoint>;\n #activity: NodeActivity;\n #newActivityBlocked = false;\n #aclServer?: AccessControlServer;\n #aclUpdateIsDelayed = false;\n\n static async create(endpoint: Endpoint<ServerNode.RootEndpoint>) {\n const endpointStructure = new InteractionEndpointStructure();\n\n const maxPathsPerInvoke = await endpoint.act(\n agent => agent.get(BasicInformationServer).state.maxPathsPerInvoke,\n );\n\n return new TransactionalInteractionServer(endpoint, {\n endpointStructure,\n subscriptionOptions: endpoint.state.network.subscriptionOptions,\n maxPathsPerInvoke,\n });\n }\n\n constructor(endpoint: Endpoint<ServerNode.RootEndpoint>, config: InteractionServer.Configuration) {\n super(config);\n\n const { endpointStructure } = config;\n\n this.#activity = endpoint.env.get(NodeActivity);\n\n this.#endpoint = endpoint;\n this.#endpointStructure = endpointStructure;\n\n // TODO - rewrite element lookup so we don't need to build the secondary endpoint structure cache\n this.#updateStructure();\n this.#changeListener = type => {\n switch (type) {\n case EndpointLifecycle.Change.PartsReady:\n case EndpointLifecycle.Change.ClientsChanged:\n case EndpointLifecycle.Change.ServersChanged:\n case EndpointLifecycle.Change.Destroyed:\n this.#updateStructure();\n break;\n }\n };\n\n endpoint.lifecycle.changed.on(this.#changeListener);\n }\n\n async [Symbol.asyncDispose]() {\n this.#endpoint.lifecycle.changed.off(this.#changeListener);\n await this.close();\n this.#endpointStructure.close();\n }\n\n blockNewActivity() {\n this.#newActivityBlocked = true;\n }\n\n override async onNewExchange(exchange: MessageExchange<MatterDevice>) {\n // When closing, ignore anything newly incoming\n if (this.#newActivityBlocked || this.isClosing) {\n return;\n }\n\n // Activity tracking. This provides diagnostic information and prevents the server from shutting down whilst\n // the exchange is active\n using activity = this.#activity.begin(`session#${exchange.session.id.toString(16)}`);\n (exchange as WithActivity)[activityKey] = activity;\n\n // Delegate to InteractionServerMessenger\n return new InteractionServerMessenger(exchange)\n .handleRequest(this)\n .finally(() => delete (exchange as WithActivity)[activityKey]);\n }\n\n get aclServer() {\n if (this.#aclServer !== undefined) {\n return this.#aclServer;\n }\n const aclServer = this.#endpoint.act(agent => agent.get(AccessControlServer));\n if (MaybePromise.is(aclServer)) {\n throw new InternalError(\"AccessControlServer should already be initialized.\");\n }\n return (this.#aclServer = aclServer);\n }\n\n protected override async readAttribute(\n path: AttributePath,\n attribute: AnyAttributeServer<any>,\n exchange: MessageExchange<MatterDevice>,\n fabricFiltered: boolean,\n message: Message,\n endpoint: EndpointInterface,\n offline = false,\n ) {\n const readAttribute = () =>\n super.readAttribute(path, attribute, exchange, fabricFiltered, message, endpoint, offline);\n\n // Offline read do not require ACL checks\n if (offline) {\n return OfflineContext.act(\"offline-read\", this.#activity, readAttribute);\n }\n\n return OnlineContext({\n activity: (exchange as WithActivity)[activityKey],\n fabricFiltered,\n message,\n exchange,\n tracer: this.#tracer,\n actionType: ActionTracer.ActionType.Read,\n endpoint,\n root: this.#endpoint,\n }).act(readAttribute);\n }\n\n protected override async readEvent(\n path: EventPath,\n eventFilters: TypeFromSchema<typeof TlvEventFilter>[] | undefined,\n event: AnyEventServer<any, any>,\n exchange: MessageExchange<MatterDevice>,\n fabricFiltered: boolean,\n message: Message,\n endpoint: EndpointInterface,\n ): Promise<EventStorageData<any>[]> {\n const readEvent = (context: ActionContext) => {\n if (!context.authorizedFor(event.readAcl, { cluster: path.clusterId } as AccessControl.Location)) {\n throw new AccessDeniedError(\n `Access to ${endpoint.number}/${Diagnostic.hex(path.clusterId)} denied on ${exchange.session.name}.`,\n );\n }\n return super.readEvent(path, eventFilters, event, exchange, fabricFiltered, message, endpoint);\n };\n\n return OnlineContext({\n activity: (exchange as WithActivity)[activityKey],\n fabricFiltered,\n message,\n exchange,\n tracer: this.#tracer,\n actionType: ActionTracer.ActionType.Read,\n endpoint,\n root: this.#endpoint,\n }).act(readEvent);\n }\n\n override async handleWriteRequest(\n exchange: MessageExchange<MatterDevice>,\n writeRequest: WriteRequest,\n message: Message,\n ): Promise<WriteResponse> {\n const result = await super.handleWriteRequest(exchange, writeRequest, message);\n\n // We delayed the ACL update during the write transaction, so we need to update it now that anything is written\n if (this.#aclUpdateIsDelayed) {\n this.aclServer.aclUpdateDelayed = false;\n this.#aclUpdateIsDelayed = false;\n }\n return result;\n }\n\n protected override async writeAttribute(\n path: AttributePath,\n attribute: AttributeServer<any>,\n value: any,\n exchange: MessageExchange<MatterDevice>,\n message: Message,\n endpoint: EndpointInterface,\n timed = false,\n isListWrite?: boolean,\n ) {\n const writeAttribute = () =>\n super.writeAttribute(path, attribute, value, exchange, message, endpoint, timed, isListWrite);\n\n if (path.endpointId === 0 && path.clusterId === AclClusterId && path.attributeId === AclAttributeId) {\n // This is a hack to prevent the ACL from updating while we are in the middle of a write transaction\n // and is needed because Acl should not become effective during writing of the ACL itself.\n this.aclServer.aclUpdateDelayed = true;\n this.#aclUpdateIsDelayed = true;\n } else if (this.#aclUpdateIsDelayed) {\n // Ok it seems that acl was written, but we now write another path, so we can update Acl attribute now\n this.aclServer.aclUpdateDelayed = false;\n this.#aclUpdateIsDelayed = false;\n }\n\n return OnlineContext({\n activity: (exchange as WithActivity)[activityKey],\n timed,\n message,\n exchange,\n fabricFiltered: true,\n tracer: this.#tracer,\n actionType: ActionTracer.ActionType.Write,\n endpoint,\n root: this.#endpoint,\n }).act(writeAttribute);\n }\n\n protected override async invokeCommand(\n path: CommandPath,\n command: CommandServer<any, any>,\n exchange: MessageExchange<MatterDevice>,\n commandFields: any,\n message: Message,\n endpoint: EndpointInterface,\n timed = false,\n ) {\n const invokeCommand = (context: ActionContext) => {\n if (!context.authorizedFor(command.invokeAcl, { cluster: path.clusterId } as AccessControl.Location)) {\n throw new AccessDeniedError(\n `Access to ${endpoint.number}/${Diagnostic.hex(path.clusterId)} denied on ${exchange.session.name}.`,\n );\n }\n return super.invokeCommand(path, command, exchange, commandFields, message, endpoint, timed);\n };\n\n return OnlineContext({\n activity: (exchange as WithActivity)[activityKey],\n command: true,\n timed,\n message,\n exchange,\n tracer: this.#tracer,\n actionType: ActionTracer.ActionType.Invoke,\n endpoint,\n root: this.#endpoint,\n }).act(invokeCommand);\n }\n\n get #tracer() {\n if (this.#endpoint.env.has(ActionTracer)) {\n return this.#endpoint.env.get(ActionTracer);\n }\n }\n\n #updateStructure() {\n if (this.#endpoint.lifecycle.isPartsReady) {\n this.#endpointStructure.initializeFromEndpoint(EndpointServer.forEndpoint(this.#endpoint));\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccessControlManager.d.ts","sourceRoot":"","sources":["../../../../src/protocol/interaction/AccessControlManager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,mDAAmD,CAAC;AAGlF,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAGxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAE/D,OAAO,EAAc,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAIlE,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAC,OAAO,aAAa,CAAC,qBAAqB,CAAC,EAAE,WAAW,CAAC,GAAG;IACzG,SAAS,EAAE,WAAW,CAAC;CAC1B,CAAC;AACF,MAAM,MAAM,OAAO,GAAG,QAAQ,EAAE,CAAC;AAEjC,MAAM,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,OAAO,aAAa,CAAC,yBAAyB,CAAC,CAAC;AACrG,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,EAAE,CAAC;AAUnD,aAAK,YAAY;IACb,IAAI,IAAI;CACX;AAED,MAAM,MAAM,yBAAyB,GAAG;IACpC,eAAe,EAAE,OAAO,CAAC;IACzB,QAAQ,EAAE,aAAa,CAAC,0BAA0B,GAAG,YAAY,CAAC;IAClE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,WAAW,CAAC;CAC5B,CAAC;AAEF,qBAAa,iBAAkB,SAAQ,mBAAmB;gBAC1C,OAAO,CAAC,EAAE,MAAM;CAG/B;AAED;;GAEG;AACH,qBAAa,oBAAoB;;gBAWzB,OAAO,GAAE,aAAa,CAAC,kBAAkB,EAAO,EAChD,yBAAyB,CAAC,EAAE,CACxB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,yBAAyB,EACtC,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,EAAE,SAAS,KACnB,OAAO;IAQhB;;OAEG;IACH,uBAAuB,CAAC,OAAO,GAAE,aAAa,CAAC,kBAAkB,EAAO,GAAG,IAAI;IAyD/E;;OAEG;IACH,eAAe,CACX,OAAO,EAAE,aAAa,CAAC,GAAG,CAAC,EAC3B,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,WAAW,GACvB,OAAO;
|
|
1
|
+
{"version":3,"file":"AccessControlManager.d.ts","sourceRoot":"","sources":["../../../../src/protocol/interaction/AccessControlManager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,mDAAmD,CAAC;AAGlF,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAGxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAE/D,OAAO,EAAc,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAIlE,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAC,OAAO,aAAa,CAAC,qBAAqB,CAAC,EAAE,WAAW,CAAC,GAAG;IACzG,SAAS,EAAE,WAAW,CAAC;CAC1B,CAAC;AACF,MAAM,MAAM,OAAO,GAAG,QAAQ,EAAE,CAAC;AAEjC,MAAM,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,OAAO,aAAa,CAAC,yBAAyB,CAAC,CAAC;AACrG,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,EAAE,CAAC;AAUnD,aAAK,YAAY;IACb,IAAI,IAAI;CACX;AAED,MAAM,MAAM,yBAAyB,GAAG;IACpC,eAAe,EAAE,OAAO,CAAC;IACzB,QAAQ,EAAE,aAAa,CAAC,0BAA0B,GAAG,YAAY,CAAC;IAClE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,WAAW,CAAC;CAC5B,CAAC;AAEF,qBAAa,iBAAkB,SAAQ,mBAAmB;gBAC1C,OAAO,CAAC,EAAE,MAAM;CAG/B;AAED;;GAEG;AACH,qBAAa,oBAAoB;;gBAWzB,OAAO,GAAE,aAAa,CAAC,kBAAkB,EAAO,EAChD,yBAAyB,CAAC,EAAE,CACxB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,yBAAyB,EACtC,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,EAAE,SAAS,KACnB,OAAO;IAQhB;;OAEG;IACH,uBAAuB,CAAC,OAAO,GAAE,aAAa,CAAC,kBAAkB,EAAO,GAAG,IAAI;IAyD/E;;OAEG;IACH,eAAe,CACX,OAAO,EAAE,aAAa,CAAC,GAAG,CAAC,EAC3B,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,WAAW,GACvB,OAAO;IAoBV;;OAEG;IACH,oBAAoB,CAChB,OAAO,EAAE,aAAa,CAAC,GAAG,CAAC,EAC3B,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,EAAE,SAAS,GACrB,WAAW,EAAE;CA8KnB"}
|
|
@@ -123,10 +123,14 @@ class AccessControlManager {
|
|
|
123
123
|
return true;
|
|
124
124
|
}
|
|
125
125
|
logger.notice(
|
|
126
|
-
`Failed access control check for ${endpoint.number}
|
|
126
|
+
`Failed access control check for ${endpoint.number}/0x${(0, import_Number.toHex)(clusterId)} and fabricIndex ${session.associatedFabric.fabricIndex}, acl=`,
|
|
127
127
|
this.#getAccessControlEntriesForFabric(session.associatedFabric),
|
|
128
|
+
"with ISD=",
|
|
129
|
+
this.#getIsdFromMessage(session),
|
|
128
130
|
"granted privileges=",
|
|
129
|
-
grantedPrivileges
|
|
131
|
+
grantedPrivileges,
|
|
132
|
+
"not contains",
|
|
133
|
+
privilege
|
|
130
134
|
);
|
|
131
135
|
return false;
|
|
132
136
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/protocol/interaction/AccessControlManager.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * @license\n * Copyright 2022-2023 Project CHIP Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { AccessLevel } from \"../../cluster/Cluster.js\";\nimport { AccessControl } from \"../../cluster/definitions/AccessControlCluster.js\";\nimport { MatterFlowError } from \"../../common/MatterError.js\";\nimport { CaseAuthenticatedTag } from \"../../datatype/CaseAuthenticatedTag.js\";\nimport { ClusterId } from \"../../datatype/ClusterId.js\";\nimport { FabricIndex } from \"../../datatype/FabricIndex.js\";\nimport { NodeId } from \"../../datatype/NodeId.js\";\nimport { EndpointInterface } from \"../../endpoint/EndpointInterface.js\";\nimport { Fabric } from \"../../fabric/Fabric.js\";\nimport { Logger } from \"../../log/Logger.js\";\nimport { TypeFromBitmapSchema } from \"../../schema/BitmapSchema.js\";\nimport { SecureSession } from \"../../session/SecureSession.js\";\nimport { toHex } from \"../../util/Number.js\";\nimport { StatusCode, StatusResponseError } from \"./StatusCode.js\";\n\nconst logger = Logger.get(\"AccessControlManager\");\n\nexport type AclEntry = Omit<TypeFromBitmapSchema<typeof AccessControl.TlvAccessControlEntry>, \"privilege\"> & {\n privilege: AccessLevel;\n};\nexport type AclList = AclEntry[];\n\nexport type AclExtensionEntry = TypeFromBitmapSchema<typeof AccessControl.TlvAccessControlExtension>;\nexport type AclExtensionList = AclExtensionEntry[];\n\nconst ImplicitDefaultPaseAclEntry: AclEntry = {\n fabricIndex: FabricIndex.NO_FABRIC, // not fabric-specific\n privilege: AccessLevel.Administer,\n authMode: AccessControl.AccessControlEntryAuthMode.Pase,\n subjects: [],\n targets: [], // entire node\n};\n\nenum AuthModeNone {\n None = 0,\n}\n\nexport type IncomingSubjectDescriptor = {\n isCommissioning: boolean;\n authMode: AccessControl.AccessControlEntryAuthMode | AuthModeNone;\n subjects: NodeId[];\n fabricIndex: FabricIndex;\n};\n\nexport class AccessDeniedError extends StatusResponseError {\n constructor(message?: string) {\n super(message ?? \"Unauthorized\", StatusCode.UnsupportedAccess);\n }\n}\n\n/**\n * Implements Access Control Logic as per Matter Specification @see {@link MatterSpecification.v12.Core} \u00A7 6.6.5.2.\n */\nexport class AccessControlManager {\n #aclList: AclList;\n #extensionEntryAccessCheck: (\n aclList: AclList,\n aclEntry: AclEntry,\n subjectDesc: IncomingSubjectDescriptor,\n endpoint: EndpointInterface,\n clusterId: ClusterId,\n ) => boolean = () => true;\n\n constructor(\n aclList: AccessControl.AccessControlEntry[] = [],\n extensionEntryAccessCheck?: (\n aclList: AclList,\n aclEntry: AclEntry,\n subjectDesc: IncomingSubjectDescriptor,\n endpoint: EndpointInterface,\n clusterId: ClusterId,\n ) => boolean,\n ) {\n this.#aclList = aclList as unknown as AclList; // It is the same structure we just use an internal type for privilege\n if (extensionEntryAccessCheck !== undefined) {\n this.#extensionEntryAccessCheck = extensionEntryAccessCheck;\n }\n }\n\n /**\n * Public method used to update the Access Control List on changes.\n */\n updateAccessControlList(aclList: AccessControl.AccessControlEntry[] = []): void {\n this.#aclList = [...aclList] as unknown as AclList; // It is the same structure we just use an internal type for privilege\n }\n\n /**\n * Get the Access Control List for a given fabric.\n */\n #getAccessControlEntriesForFabric(fabric: Fabric): AclList {\n return this.#aclList.filter(entry => entry.fabricIndex === fabric.fabricIndex);\n }\n\n /**\n * Subjects must match exactly, or both are CAT with matching CAT ID and acceptable CAT version\n */\n #subjectMatches(aclSubject: NodeId, isdSubject: NodeId): boolean {\n if (aclSubject === isdSubject) {\n return true;\n }\n if (!NodeId.isCaseAuthenticatedTag(aclSubject) || !NodeId.isCaseAuthenticatedTag(isdSubject)) {\n return false;\n }\n const aclSubjectCat = NodeId.extractAsCaseAuthenticatedTag(aclSubject);\n const isdSubjectCat = NodeId.extractAsCaseAuthenticatedTag(isdSubject);\n return (\n CaseAuthenticatedTag.getIdentifyValue(aclSubjectCat) ===\n CaseAuthenticatedTag.getIdentifyValue(isdSubjectCat) &&\n CaseAuthenticatedTag.getVersion(isdSubjectCat) >= CaseAuthenticatedTag.getVersion(aclSubjectCat)\n );\n }\n\n /**\n * Add the new privilege to the granted privileges set and also add any privileges subsumed by the new privilege.\n */\n #addGrantedPrivilege(grantedPrivileges: Set<AccessLevel>, privilege: AccessLevel): void {\n // Add the new privilege to the granted privileges set\n grantedPrivileges.add(privilege);\n // Also add any privileges subsumed by the new privilege\n switch (privilege) {\n case AccessLevel.ProxyView:\n grantedPrivileges.add(AccessLevel.View);\n break;\n case AccessLevel.Operate:\n grantedPrivileges.add(AccessLevel.View);\n break;\n case AccessLevel.Manage:\n grantedPrivileges.add(AccessLevel.Operate);\n grantedPrivileges.add(AccessLevel.View);\n break;\n case AccessLevel.Administer:\n grantedPrivileges.add(AccessLevel.Manage);\n grantedPrivileges.add(AccessLevel.Operate);\n grantedPrivileges.add(AccessLevel.ProxyView);\n grantedPrivileges.add(AccessLevel.View);\n break;\n }\n }\n\n /**\n * Check if the given ACL entry is allowed to be used for the given subject descriptor, endpoint, and cluster ID.\n */\n allowsPrivilege(\n session: SecureSession<any>,\n endpoint: EndpointInterface,\n clusterId: ClusterId,\n privilege: AccessLevel,\n ): boolean {\n const grantedPrivileges = this.getGrantedPrivileges(session, endpoint, clusterId);\n if (grantedPrivileges.includes(privilege)) {\n return true;\n }\n\n logger.notice(\n `Failed access control check for ${endpoint.number}/${toHex(clusterId)} and fabricIndex ${session.associatedFabric.fabricIndex}, acl=`,\n this.#getAccessControlEntriesForFabric(session.associatedFabric),\n \"granted privileges=\",\n grantedPrivileges,\n );\n\n return false;\n }\n\n /**\n * Determines the granted privileges for the given session, endpoint, and cluster ID and returns them.\n */\n getGrantedPrivileges(\n session: SecureSession<any>,\n endpoint: EndpointInterface,\n clusterId: ClusterId,\n ): AccessLevel[] {\n const endpointId = endpoint.number;\n const fabric = session.fabric;\n const subjectDesc = this.#getIsdFromMessage(session);\n const acl = fabric ? this.#getAccessControlEntriesForFabric(fabric) : [ImplicitDefaultPaseAclEntry];\n\n // Granted privileges set is initially empty\n const grantedPrivileges = new Set<AccessLevel>();\n\n // PASE commissioning channel implicitly grants administer privilege to commissioner\n if (subjectDesc.authMode === AccessControl.AccessControlEntryAuthMode.Pase && subjectDesc.isCommissioning) {\n this.#addGrantedPrivilege(grantedPrivileges, AccessLevel.Administer);\n }\n\n for (const aclEntry of acl) {\n if (grantedPrivileges.has(AccessLevel.Administer)) {\n // End checking if highest privilege is granted\n break;\n }\n\n // Fabric index must match, there are no valid entries with FabricIndex == 0\n // other than the implicit PASE entry, which we will not see explicitly in the\n // access control list\n if (aclEntry.fabricIndex === FabricIndex.NO_FABRIC || aclEntry.fabricIndex !== subjectDesc.fabricIndex) {\n logger.debug(\n \"Skipping ACL entry with mismatched fabric index\",\n aclEntry.fabricIndex,\n subjectDesc.fabricIndex,\n );\n continue;\n }\n\n // Auth mode must match\n if (aclEntry.authMode !== subjectDesc.authMode) {\n logger.debug(\"Skipping ACL entry with mismatched auth mode\", aclEntry.authMode, subjectDesc.authMode);\n continue;\n }\n\n // Subject must match, or be \"wildcard\"\n if (aclEntry.subjects === null || aclEntry.subjects.length === 0) {\n // Precondition: only CASE and Group auth can have empty subjects\n if (\n aclEntry.authMode !== AccessControl.AccessControlEntryAuthMode.Case &&\n aclEntry.authMode !== AccessControl.AccessControlEntryAuthMode.Group\n ) {\n throw new MatterFlowError(\"ACL error: only CASE and Group auth can have empty subjects\");\n }\n // ... Empty is wildcard, no match required\n } else {\n // Non-empty requires a match\n let matchedSubject = false;\n subjectLoop: for (const aclSubject of aclEntry.subjects) {\n for (const isdSubject of subjectDesc.subjects) {\n if (this.#subjectMatches(aclSubject, isdSubject)) {\n matchedSubject = true;\n break subjectLoop;\n }\n }\n }\n if (!matchedSubject) {\n continue;\n }\n }\n\n // Target must match, or be \"wildcard\"\n if (aclEntry.targets === null || aclEntry.targets.length === 0) {\n // Empty is wildcard, no match required\n } else {\n // Non-empty requires a match\n let matchedTarget = false;\n for (const {\n cluster: targetClusterId,\n endpoint: targetEndpointId,\n deviceType: targetDeviceType,\n } of aclEntry.targets) {\n // Precondition: target cannot be empty\n if (targetClusterId === null && targetEndpointId === null && targetDeviceType === null) {\n throw new MatterFlowError(\"ACL error: target cannot be empty\");\n }\n // Precondition: target cannot specify both endpoint and device type\n if (targetEndpointId !== null && targetDeviceType !== null) {\n throw new MatterFlowError(\"ACL error: target cannot specify both endpoint and device type\");\n }\n // Cluster must match, or be wildcard\n if (targetClusterId !== null && targetClusterId !== clusterId) {\n continue;\n }\n // Endpoint must match, or be wildcard\n if (targetEndpointId !== null && targetEndpointId !== endpointId) {\n continue;\n }\n // Endpoint may be specified indirectly via device type\n // TODO adjust to array check once we use multiple devicetypes\n if (targetDeviceType !== null && endpoint.deviceType !== targetDeviceType) {\n continue;\n }\n matchedTarget = true;\n break;\n }\n if (!matchedTarget) {\n continue;\n }\n }\n\n // Extensions processing must not fail\n if (!this.#extensionEntryAccessCheck(acl, aclEntry, subjectDesc, endpoint, clusterId)) {\n continue;\n }\n\n // All checks have passed, add privilege to granted privilege set\n this.#addGrantedPrivilege(grantedPrivileges, aclEntry.privilege);\n }\n // Should never grant Administer privilege to a Group.\n if (\n subjectDesc.authMode === AccessControl.AccessControlEntryAuthMode.Group &&\n grantedPrivileges.has(AccessLevel.Administer)\n ) {\n throw new MatterFlowError(\"ACL error: should never grant Administer privilege to a Group\");\n }\n\n return [...grantedPrivileges];\n }\n\n /**\n * Determines the Incoming Subject Descriptor (ISD) from the given session.\n */\n #getIsdFromMessage(session: SecureSession<any>) {\n const fabric = session.fabric;\n const isd: IncomingSubjectDescriptor = {\n isCommissioning: false,\n authMode: AuthModeNone.None,\n subjects: new Array<NodeId>(),\n fabricIndex: FabricIndex.NO_FABRIC,\n };\n\n if (session.isPase) {\n isd.authMode = AccessControl.AccessControlEntryAuthMode.Pase;\n isd.isCommissioning = true; // Or how \"commissioning channel\" is defined?\n isd.subjects.push(NodeId(0)); // Default Commissioning Passcode ID\n if (fabric) {\n isd.fabricIndex = fabric.fabricIndex;\n }\n } else {\n // TODO Add Group session handling when implementing groups\n // if (session instanceof SecureGroupSession) {\n // Groups\n // # Message is assumed to have been decrypted and matched properly prior to\n // # this procedure occurring.\n // group_id = message.get_dst_group_id()\n // group_key_id = sessions_metadata.get_group_key_id(message)\n // # Group membership must be verified against Group Key Management Cluster\n // if group_key_management_cluster.group_key_map_has_mapping(group_id, group_key_id):\n // isd.AuthMode = AuthModeEnum.Group\n // isd.Subjects.append(group_id)\n // isd.FabricIndex = sessions_metadata.get_fabric_index(message)\n // assert(isd.FabricIndex != 0) # cannot be zero\n //\n // isd.authMode = AccessControl.AccessControlEntryAuthMode.Group;\n // } else {\n\n // CASE session\n isd.authMode = AccessControl.AccessControlEntryAuthMode.Case;\n isd.subjects.push(session.peerNodeId);\n // Append CASE session CATs which also serve as subjects\n session.caseAuthenticatedTags.forEach(cat => isd.subjects.push(NodeId.fromCaseAuthenticatedTag(cat)));\n // }\n if (fabric === undefined) {\n throw new MatterFlowError(\"ACL error: fabric is undefined\");\n }\n isd.fabricIndex = fabric.fabricIndex;\n }\n\n return isd;\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,qBAA4B;AAC5B,kCAA8B;AAC9B,yBAAgC;AAChC,kCAAqC;AAErC,yBAA4B;AAC5B,oBAAuB;AAGvB,oBAAuB;AAGvB,oBAAsB;AACtB,wBAAgD;AAlBhD;AAAA;AAAA;AAAA;AAAA;AAoBA,MAAM,SAAS,qBAAO,IAAI,sBAAsB;AAUhD,MAAM,8BAAwC;AAAA,EAC1C,aAAa,+BAAY;AAAA;AAAA,EACzB,WAAW,2BAAY;AAAA,EACvB,UAAU,0CAAc,2BAA2B;AAAA,EACnD,UAAU,CAAC;AAAA,EACX,SAAS,CAAC;AAAA;AACd;AAEA,IAAK,eAAL,kBAAKA,kBAAL;AACI,EAAAA,4BAAA,UAAO,KAAP;AADC,SAAAA;AAAA,GAAA;AAWE,MAAM,0BAA0B,sCAAoB;AAAA,EACvD,YAAY,SAAkB;AAC1B,UAAM,WAAW,gBAAgB,6BAAW,iBAAiB;AAAA,EACjE;AACJ;AAKO,MAAM,qBAAqB;AAAA,EAC9B;AAAA,EACA,6BAMe,MAAM;AAAA,EAErB,YACI,UAA8C,CAAC,GAC/C,2BAOF;AACE,SAAK,WAAW;AAChB,QAAI,8BAA8B,QAAW;AACzC,WAAK,6BAA6B;AAAA,IACtC;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,wBAAwB,UAA8C,CAAC,GAAS;AAC5E,SAAK,WAAW,CAAC,GAAG,OAAO;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,kCAAkC,QAAyB;AACvD,WAAO,KAAK,SAAS,OAAO,WAAS,MAAM,gBAAgB,OAAO,WAAW;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,YAAoB,YAA6B;AAC7D,QAAI,eAAe,YAAY;AAC3B,aAAO;AAAA,IACX;AACA,QAAI,CAAC,qBAAO,uBAAuB,UAAU,KAAK,CAAC,qBAAO,uBAAuB,UAAU,GAAG;AAC1F,aAAO;AAAA,IACX;AACA,UAAM,gBAAgB,qBAAO,8BAA8B,UAAU;AACrE,UAAM,gBAAgB,qBAAO,8BAA8B,UAAU;AACrE,WACI,iDAAqB,iBAAiB,aAAa,MAC/C,iDAAqB,iBAAiB,aAAa,KACvD,iDAAqB,WAAW,aAAa,KAAK,iDAAqB,WAAW,aAAa;AAAA,EAEvG;AAAA;AAAA;AAAA;AAAA,EAKA,qBAAqB,mBAAqC,WAA8B;AAEpF,sBAAkB,IAAI,SAAS;AAE/B,YAAQ,WAAW;AAAA,MACf,KAAK,2BAAY;AACb,0BAAkB,IAAI,2BAAY,IAAI;AACtC;AAAA,MACJ,KAAK,2BAAY;AACb,0BAAkB,IAAI,2BAAY,IAAI;AACtC;AAAA,MACJ,KAAK,2BAAY;AACb,0BAAkB,IAAI,2BAAY,OAAO;AACzC,0BAAkB,IAAI,2BAAY,IAAI;AACtC;AAAA,MACJ,KAAK,2BAAY;AACb,0BAAkB,IAAI,2BAAY,MAAM;AACxC,0BAAkB,IAAI,2BAAY,OAAO;AACzC,0BAAkB,IAAI,2BAAY,SAAS;AAC3C,0BAAkB,IAAI,2BAAY,IAAI;AACtC;AAAA,IACR;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,gBACI,SACA,UACA,WACA,WACO;AACP,UAAM,oBAAoB,KAAK,qBAAqB,SAAS,UAAU,SAAS;AAChF,QAAI,kBAAkB,SAAS,SAAS,GAAG;AACvC,aAAO;AAAA,IACX;AAEA,WAAO;AAAA,MACH,mCAAmC,SAAS,MAAM,
|
|
4
|
+
"sourcesContent": ["/**\n * @license\n * Copyright 2022-2023 Project CHIP Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { AccessLevel } from \"../../cluster/Cluster.js\";\nimport { AccessControl } from \"../../cluster/definitions/AccessControlCluster.js\";\nimport { MatterFlowError } from \"../../common/MatterError.js\";\nimport { CaseAuthenticatedTag } from \"../../datatype/CaseAuthenticatedTag.js\";\nimport { ClusterId } from \"../../datatype/ClusterId.js\";\nimport { FabricIndex } from \"../../datatype/FabricIndex.js\";\nimport { NodeId } from \"../../datatype/NodeId.js\";\nimport { EndpointInterface } from \"../../endpoint/EndpointInterface.js\";\nimport { Fabric } from \"../../fabric/Fabric.js\";\nimport { Logger } from \"../../log/Logger.js\";\nimport { TypeFromBitmapSchema } from \"../../schema/BitmapSchema.js\";\nimport { SecureSession } from \"../../session/SecureSession.js\";\nimport { toHex } from \"../../util/Number.js\";\nimport { StatusCode, StatusResponseError } from \"./StatusCode.js\";\n\nconst logger = Logger.get(\"AccessControlManager\");\n\nexport type AclEntry = Omit<TypeFromBitmapSchema<typeof AccessControl.TlvAccessControlEntry>, \"privilege\"> & {\n privilege: AccessLevel;\n};\nexport type AclList = AclEntry[];\n\nexport type AclExtensionEntry = TypeFromBitmapSchema<typeof AccessControl.TlvAccessControlExtension>;\nexport type AclExtensionList = AclExtensionEntry[];\n\nconst ImplicitDefaultPaseAclEntry: AclEntry = {\n fabricIndex: FabricIndex.NO_FABRIC, // not fabric-specific\n privilege: AccessLevel.Administer,\n authMode: AccessControl.AccessControlEntryAuthMode.Pase,\n subjects: [],\n targets: [], // entire node\n};\n\nenum AuthModeNone {\n None = 0,\n}\n\nexport type IncomingSubjectDescriptor = {\n isCommissioning: boolean;\n authMode: AccessControl.AccessControlEntryAuthMode | AuthModeNone;\n subjects: NodeId[];\n fabricIndex: FabricIndex;\n};\n\nexport class AccessDeniedError extends StatusResponseError {\n constructor(message?: string) {\n super(message ?? \"Unauthorized\", StatusCode.UnsupportedAccess);\n }\n}\n\n/**\n * Implements Access Control Logic as per Matter Specification @see {@link MatterSpecification.v12.Core} \u00A7 6.6.5.2.\n */\nexport class AccessControlManager {\n #aclList: AclList;\n #extensionEntryAccessCheck: (\n aclList: AclList,\n aclEntry: AclEntry,\n subjectDesc: IncomingSubjectDescriptor,\n endpoint: EndpointInterface,\n clusterId: ClusterId,\n ) => boolean = () => true;\n\n constructor(\n aclList: AccessControl.AccessControlEntry[] = [],\n extensionEntryAccessCheck?: (\n aclList: AclList,\n aclEntry: AclEntry,\n subjectDesc: IncomingSubjectDescriptor,\n endpoint: EndpointInterface,\n clusterId: ClusterId,\n ) => boolean,\n ) {\n this.#aclList = aclList as unknown as AclList; // It is the same structure we just use an internal type for privilege\n if (extensionEntryAccessCheck !== undefined) {\n this.#extensionEntryAccessCheck = extensionEntryAccessCheck;\n }\n }\n\n /**\n * Public method used to update the Access Control List on changes.\n */\n updateAccessControlList(aclList: AccessControl.AccessControlEntry[] = []): void {\n this.#aclList = [...aclList] as unknown as AclList; // It is the same structure we just use an internal type for privilege\n }\n\n /**\n * Get the Access Control List for a given fabric.\n */\n #getAccessControlEntriesForFabric(fabric: Fabric): AclList {\n return this.#aclList.filter(entry => entry.fabricIndex === fabric.fabricIndex);\n }\n\n /**\n * Subjects must match exactly, or both are CAT with matching CAT ID and acceptable CAT version\n */\n #subjectMatches(aclSubject: NodeId, isdSubject: NodeId): boolean {\n if (aclSubject === isdSubject) {\n return true;\n }\n if (!NodeId.isCaseAuthenticatedTag(aclSubject) || !NodeId.isCaseAuthenticatedTag(isdSubject)) {\n return false;\n }\n const aclSubjectCat = NodeId.extractAsCaseAuthenticatedTag(aclSubject);\n const isdSubjectCat = NodeId.extractAsCaseAuthenticatedTag(isdSubject);\n return (\n CaseAuthenticatedTag.getIdentifyValue(aclSubjectCat) ===\n CaseAuthenticatedTag.getIdentifyValue(isdSubjectCat) &&\n CaseAuthenticatedTag.getVersion(isdSubjectCat) >= CaseAuthenticatedTag.getVersion(aclSubjectCat)\n );\n }\n\n /**\n * Add the new privilege to the granted privileges set and also add any privileges subsumed by the new privilege.\n */\n #addGrantedPrivilege(grantedPrivileges: Set<AccessLevel>, privilege: AccessLevel): void {\n // Add the new privilege to the granted privileges set\n grantedPrivileges.add(privilege);\n // Also add any privileges subsumed by the new privilege\n switch (privilege) {\n case AccessLevel.ProxyView:\n grantedPrivileges.add(AccessLevel.View);\n break;\n case AccessLevel.Operate:\n grantedPrivileges.add(AccessLevel.View);\n break;\n case AccessLevel.Manage:\n grantedPrivileges.add(AccessLevel.Operate);\n grantedPrivileges.add(AccessLevel.View);\n break;\n case AccessLevel.Administer:\n grantedPrivileges.add(AccessLevel.Manage);\n grantedPrivileges.add(AccessLevel.Operate);\n grantedPrivileges.add(AccessLevel.ProxyView);\n grantedPrivileges.add(AccessLevel.View);\n break;\n }\n }\n\n /**\n * Check if the given ACL entry is allowed to be used for the given subject descriptor, endpoint, and cluster ID.\n */\n allowsPrivilege(\n session: SecureSession<any>,\n endpoint: EndpointInterface,\n clusterId: ClusterId,\n privilege: AccessLevel,\n ): boolean {\n const grantedPrivileges = this.getGrantedPrivileges(session, endpoint, clusterId);\n if (grantedPrivileges.includes(privilege)) {\n return true;\n }\n\n logger.notice(\n `Failed access control check for ${endpoint.number}/0x${toHex(clusterId)} and fabricIndex ${session.associatedFabric.fabricIndex}, acl=`,\n this.#getAccessControlEntriesForFabric(session.associatedFabric),\n \"with ISD=\",\n this.#getIsdFromMessage(session),\n \"granted privileges=\",\n grantedPrivileges,\n \"not contains\",\n privilege,\n );\n\n return false;\n }\n\n /**\n * Determines the granted privileges for the given session, endpoint, and cluster ID and returns them.\n */\n getGrantedPrivileges(\n session: SecureSession<any>,\n endpoint: EndpointInterface,\n clusterId: ClusterId,\n ): AccessLevel[] {\n const endpointId = endpoint.number;\n const fabric = session.fabric;\n const subjectDesc = this.#getIsdFromMessage(session);\n const acl = fabric ? this.#getAccessControlEntriesForFabric(fabric) : [ImplicitDefaultPaseAclEntry];\n\n // Granted privileges set is initially empty\n const grantedPrivileges = new Set<AccessLevel>();\n\n // PASE commissioning channel implicitly grants administer privilege to commissioner\n if (subjectDesc.authMode === AccessControl.AccessControlEntryAuthMode.Pase && subjectDesc.isCommissioning) {\n this.#addGrantedPrivilege(grantedPrivileges, AccessLevel.Administer);\n }\n\n for (const aclEntry of acl) {\n if (grantedPrivileges.has(AccessLevel.Administer)) {\n // End checking if highest privilege is granted\n break;\n }\n\n // Fabric index must match, there are no valid entries with FabricIndex == 0\n // other than the implicit PASE entry, which we will not see explicitly in the\n // access control list\n if (aclEntry.fabricIndex === FabricIndex.NO_FABRIC || aclEntry.fabricIndex !== subjectDesc.fabricIndex) {\n logger.debug(\n \"Skipping ACL entry with mismatched fabric index\",\n aclEntry.fabricIndex,\n subjectDesc.fabricIndex,\n );\n continue;\n }\n\n // Auth mode must match\n if (aclEntry.authMode !== subjectDesc.authMode) {\n logger.debug(\"Skipping ACL entry with mismatched auth mode\", aclEntry.authMode, subjectDesc.authMode);\n continue;\n }\n\n // Subject must match, or be \"wildcard\"\n if (aclEntry.subjects === null || aclEntry.subjects.length === 0) {\n // Precondition: only CASE and Group auth can have empty subjects\n if (\n aclEntry.authMode !== AccessControl.AccessControlEntryAuthMode.Case &&\n aclEntry.authMode !== AccessControl.AccessControlEntryAuthMode.Group\n ) {\n throw new MatterFlowError(\"ACL error: only CASE and Group auth can have empty subjects\");\n }\n // ... Empty is wildcard, no match required\n } else {\n // Non-empty requires a match\n let matchedSubject = false;\n subjectLoop: for (const aclSubject of aclEntry.subjects) {\n for (const isdSubject of subjectDesc.subjects) {\n if (this.#subjectMatches(aclSubject, isdSubject)) {\n matchedSubject = true;\n break subjectLoop;\n }\n }\n }\n if (!matchedSubject) {\n continue;\n }\n }\n\n // Target must match, or be \"wildcard\"\n if (aclEntry.targets === null || aclEntry.targets.length === 0) {\n // Empty is wildcard, no match required\n } else {\n // Non-empty requires a match\n let matchedTarget = false;\n for (const {\n cluster: targetClusterId,\n endpoint: targetEndpointId,\n deviceType: targetDeviceType,\n } of aclEntry.targets) {\n // Precondition: target cannot be empty\n if (targetClusterId === null && targetEndpointId === null && targetDeviceType === null) {\n throw new MatterFlowError(\"ACL error: target cannot be empty\");\n }\n // Precondition: target cannot specify both endpoint and device type\n if (targetEndpointId !== null && targetDeviceType !== null) {\n throw new MatterFlowError(\"ACL error: target cannot specify both endpoint and device type\");\n }\n // Cluster must match, or be wildcard\n if (targetClusterId !== null && targetClusterId !== clusterId) {\n continue;\n }\n // Endpoint must match, or be wildcard\n if (targetEndpointId !== null && targetEndpointId !== endpointId) {\n continue;\n }\n // Endpoint may be specified indirectly via device type\n // TODO adjust to array check once we use multiple devicetypes\n if (targetDeviceType !== null && endpoint.deviceType !== targetDeviceType) {\n continue;\n }\n matchedTarget = true;\n break;\n }\n if (!matchedTarget) {\n continue;\n }\n }\n\n // Extensions processing must not fail\n if (!this.#extensionEntryAccessCheck(acl, aclEntry, subjectDesc, endpoint, clusterId)) {\n continue;\n }\n\n // All checks have passed, add privilege to granted privilege set\n this.#addGrantedPrivilege(grantedPrivileges, aclEntry.privilege);\n }\n // Should never grant Administer privilege to a Group.\n if (\n subjectDesc.authMode === AccessControl.AccessControlEntryAuthMode.Group &&\n grantedPrivileges.has(AccessLevel.Administer)\n ) {\n throw new MatterFlowError(\"ACL error: should never grant Administer privilege to a Group\");\n }\n\n return [...grantedPrivileges];\n }\n\n /**\n * Determines the Incoming Subject Descriptor (ISD) from the given session.\n */\n #getIsdFromMessage(session: SecureSession<any>) {\n const fabric = session.fabric;\n const isd: IncomingSubjectDescriptor = {\n isCommissioning: false,\n authMode: AuthModeNone.None,\n subjects: new Array<NodeId>(),\n fabricIndex: FabricIndex.NO_FABRIC,\n };\n\n if (session.isPase) {\n isd.authMode = AccessControl.AccessControlEntryAuthMode.Pase;\n isd.isCommissioning = true; // Or how \"commissioning channel\" is defined?\n isd.subjects.push(NodeId(0)); // Default Commissioning Passcode ID\n if (fabric) {\n isd.fabricIndex = fabric.fabricIndex;\n }\n } else {\n // TODO Add Group session handling when implementing groups\n // if (session instanceof SecureGroupSession) {\n // Groups\n // # Message is assumed to have been decrypted and matched properly prior to\n // # this procedure occurring.\n // group_id = message.get_dst_group_id()\n // group_key_id = sessions_metadata.get_group_key_id(message)\n // # Group membership must be verified against Group Key Management Cluster\n // if group_key_management_cluster.group_key_map_has_mapping(group_id, group_key_id):\n // isd.AuthMode = AuthModeEnum.Group\n // isd.Subjects.append(group_id)\n // isd.FabricIndex = sessions_metadata.get_fabric_index(message)\n // assert(isd.FabricIndex != 0) # cannot be zero\n //\n // isd.authMode = AccessControl.AccessControlEntryAuthMode.Group;\n // } else {\n\n // CASE session\n isd.authMode = AccessControl.AccessControlEntryAuthMode.Case;\n isd.subjects.push(session.peerNodeId);\n // Append CASE session CATs which also serve as subjects\n session.caseAuthenticatedTags.forEach(cat => isd.subjects.push(NodeId.fromCaseAuthenticatedTag(cat)));\n // }\n if (fabric === undefined) {\n throw new MatterFlowError(\"ACL error: fabric is undefined\");\n }\n isd.fabricIndex = fabric.fabricIndex;\n }\n\n return isd;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["AuthModeNone"]
|
|
7
7
|
}
|
|
@@ -79,7 +79,7 @@ export declare class InteractionServer implements ProtocolHandler<MatterDevice>,
|
|
|
79
79
|
get maxPathsPerInvoke(): number;
|
|
80
80
|
onNewExchange(exchange: MessageExchange<MatterDevice>): Promise<void>;
|
|
81
81
|
handleReadRequest(exchange: MessageExchange<MatterDevice>, { attributeRequests, dataVersionFilters, eventRequests, eventFilters, isFabricFiltered, interactionModelRevision, }: ReadRequest, message: Message): Promise<DataReportPayload>;
|
|
82
|
-
protected readAttribute(_path: AttributePath, attribute: AnyAttributeServer<any>, exchange: MessageExchange<MatterDevice>, isFabricFiltered: boolean, message: Message, _endpoint: EndpointInterface): Promise<{
|
|
82
|
+
protected readAttribute(_path: AttributePath, attribute: AnyAttributeServer<any>, exchange: MessageExchange<MatterDevice>, isFabricFiltered: boolean, message: Message, _endpoint: EndpointInterface, offline?: boolean): Promise<{
|
|
83
83
|
version: number;
|
|
84
84
|
value: any;
|
|
85
85
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InteractionServer.d.ts","sourceRoot":"","sources":["../../../../src/protocol/interaction/InteractionServer.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"InteractionServer.d.ts","sourceRoot":"","sources":["../../../../src/protocol/interaction/InteractionServer.ts"],"names":[],"mappings":"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"}
|
|
@@ -409,8 +409,8 @@ class InteractionServer {
|
|
|
409
409
|
eventReportsPayload
|
|
410
410
|
};
|
|
411
411
|
}
|
|
412
|
-
async readAttribute(_path, attribute, exchange, isFabricFiltered, message, _endpoint) {
|
|
413
|
-
return attribute.getWithVersion(exchange.session, isFabricFiltered, message);
|
|
412
|
+
async readAttribute(_path, attribute, exchange, isFabricFiltered, message, _endpoint, offline = false) {
|
|
413
|
+
return attribute.getWithVersion(exchange.session, isFabricFiltered, offline ? void 0 : message);
|
|
414
414
|
}
|
|
415
415
|
async readEvent(_path, eventFilters, event, exchange, isFabricFiltered, message, _endpoint) {
|
|
416
416
|
return event.get(exchange.session, isFabricFiltered, message, eventFilters);
|
|
@@ -722,13 +722,14 @@ class InteractionServer {
|
|
|
722
722
|
maxIntervalCeiling: maxIntervalCeilingSeconds,
|
|
723
723
|
cancelCallback: () => this.#subscriptionMap.delete(subscriptionId),
|
|
724
724
|
subscriptionOptions: this.#subscriptionConfig,
|
|
725
|
-
readAttribute: (path, attribute) => this.readAttribute(
|
|
725
|
+
readAttribute: (path, attribute, offline) => this.readAttribute(
|
|
726
726
|
path,
|
|
727
727
|
attribute,
|
|
728
728
|
exchange,
|
|
729
729
|
isFabricFiltered,
|
|
730
730
|
message,
|
|
731
|
-
this.#endpointStructure.getEndpoint(path.endpointId)
|
|
731
|
+
this.#endpointStructure.getEndpoint(path.endpointId),
|
|
732
|
+
offline
|
|
732
733
|
),
|
|
733
734
|
readEvent: (path, event, eventFilters2) => this.readEvent(
|
|
734
735
|
path,
|