@awarevue/agent-sdk 1.0.30 → 1.0.31

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.
@@ -18,6 +18,7 @@ export declare class AgentApp {
18
18
  private sub;
19
19
  private getReply$;
20
20
  private addEnvelope;
21
+ private createAccessChangeContext;
21
22
  private runProvider$;
22
23
  private process$;
23
24
  constructor(agent: Agent, options: AgentOptions);
package/dist/agent-app.js CHANGED
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AgentApp = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
+ const default_validator_1 = require("./default-validator");
5
6
  class AgentApp {
6
7
  constructor(agent, options) {
7
8
  this.agent = agent;
@@ -31,7 +32,32 @@ class AgentApp {
31
32
  version: this.options.version,
32
33
  on: Date.now(),
33
34
  });
35
+ this.createAccessChangeContext = (context, refMap, objectCache) => {
36
+ return {
37
+ ...context,
38
+ objectsById: (objectKind, objectId) => {
39
+ const objectKindRefs = refMap[objectKind] || {};
40
+ const refs = objectKindRefs[objectId] || [];
41
+ return refs.flatMap((foreignRef) => {
42
+ const value = objectCache[objectKind][foreignRef];
43
+ return value ? [value] : [];
44
+ });
45
+ },
46
+ objectByForeignRef: (objectKind, foreignRef) => {
47
+ return objectCache[objectKind][foreignRef] || null;
48
+ },
49
+ };
50
+ };
34
51
  this.runProvider$ = (context) => {
52
+ const changeValidator$ = (0, default_validator_1.createValidator)(this.agent);
53
+ // we assume that there will be only one validate-apply cycle per agent at the same time
54
+ let objectCache = {
55
+ person: {},
56
+ accessRule: {},
57
+ schedule: {},
58
+ device: {},
59
+ zone: {},
60
+ };
35
61
  return (0, rxjs_1.merge)(
36
62
  // run the agent monitor
37
63
  this.agent
@@ -81,7 +107,14 @@ class AgentApp {
81
107
  // validate access change
82
108
  const validateOb$ = !this.agent.validateAccessChange$
83
109
  ? (0, rxjs_1.throwError)(() => new Error(`Agent ${context.provider} does not support access change validation`))
84
- : this.agent.validateAccessChange$(context, message);
110
+ : changeValidator$(context, message).pipe((0, rxjs_1.mergeMap)(([issues, cache]) => {
111
+ objectCache = cache;
112
+ const validationContext = this.createAccessChangeContext(context, message.refMap, objectCache);
113
+ return issues.length > 0
114
+ ? (0, rxjs_1.of)(issues)
115
+ : this.agent.validateAccessChange$(validationContext, message);
116
+ return (0, rxjs_1.of)(issues);
117
+ }));
85
118
  return validateOb$.pipe((0, rxjs_1.map)((issues) => ({
86
119
  kind: 'validate-change-rs',
87
120
  requestId: message.id,
@@ -96,9 +129,10 @@ class AgentApp {
96
129
  }), (0, rxjs_1.tap)((rs) => this.options.transport.send(this.addEnvelope(rs))));
97
130
  case 'apply-change':
98
131
  // apply access change
132
+ const applyContext = this.createAccessChangeContext(context, message.refMap, objectCache);
99
133
  const applyOb$ = !this.agent.applyAccessChange$
100
134
  ? (0, rxjs_1.throwError)(() => new Error(`Agent ${context.provider} does not support access change application`))
101
- : this.agent.applyAccessChange$(context, message);
135
+ : this.agent.applyAccessChange$(applyContext, message);
102
136
  return applyOb$.pipe((0, rxjs_1.map)((result) => ({
103
137
  kind: 'apply-change-rs',
104
138
  requestId: message.id,
package/dist/agent.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ValidateProviderConfigRs, DeviceDiscoveryDto, RunCommandRq, AccessValidateChangeRq, AccessChangeIssue, AccessApplyChange, AccessRefMap } from '@awarevue/api-types';
1
+ import { ValidateProviderConfigRs, DeviceDiscoveryDto, RunCommandRq, AccessValidateChangeRq, AccessChangeIssue, AccessApplyChange, AccessRefMap, AccessObjectKind } from '@awarevue/api-types';
2
2
  import { Observable } from 'rxjs';
3
3
  import { DeviceActivity } from './agent-app';
4
4
  export type Context = {
@@ -15,6 +15,8 @@ export type RunCommandContext = Context & {
15
15
  };
16
16
  export type AccessChangeContext = Context & {
17
17
  deviceCatalog: DeviceDiscoveryDto;
18
+ objectsById: <T extends Record<string, unknown>>(objectKind: AccessObjectKind, objectId: string) => T[];
19
+ objectByForeignRef: <T extends Record<string, unknown>>(objectKind: AccessObjectKind, foreignRef: string) => T | null;
18
20
  };
19
21
  export interface Agent {
20
22
  getConfigIssues$: (context: Context) => Observable<ValidateProviderConfigRs['issues']>;
@@ -23,4 +25,5 @@ export interface Agent {
23
25
  runCommand$: (context: RunCommandContext, command: RunCommandRq) => Observable<unknown>;
24
26
  validateAccessChange$?: (context: AccessChangeContext, change: AccessValidateChangeRq) => Observable<AccessChangeIssue[]>;
25
27
  applyAccessChange$?: (context: AccessChangeContext, change: AccessApplyChange) => Observable<AccessRefMap>;
28
+ find$?: (context: Context, objectKind: AccessObjectKind, objectIds: string[]) => Observable<Record<string, Record<string, unknown>[]>>;
26
29
  }
@@ -0,0 +1,10 @@
1
+ import { AccessValidateChangeRq } from '@awarevue/api-types';
2
+ import { Agent, Context } from './agent';
3
+ export declare const createValidator: <T extends Agent>(agent: T) => (context: Context, change: AccessValidateChangeRq) => import("rxjs").Observable<readonly [{
4
+ index?: number | undefined;
5
+ code?: "BAD_REFERENCE" | "NOT_FOUND" | "NOT_UNIQUE" | "INVALID" | "NOT_SUPPORTED" | undefined;
6
+ message?: string | undefined;
7
+ path?: string | undefined;
8
+ objectKind?: "person" | "zone" | "device" | "schedule" | "accessRule" | undefined;
9
+ objectId?: string | undefined;
10
+ }[], Record<"accessRule" | "schedule" | "person" | "device" | "zone", Record<string, Record<string, unknown>>>]>;
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createValidator = void 0;
4
+ const rxjs_1 = require("rxjs");
5
+ const emptyMap = {};
6
+ const createValidator = (agent) => {
7
+ const getNotFoundIssues = (req) => {
8
+ // check object ref contains all related objects
9
+ const personIds = [
10
+ ...new Set(req.mutations.flatMap((m) => {
11
+ var _a;
12
+ return m.kind === 'merge' && m.objectKind === 'accessRule'
13
+ ? ((_a = m.props.appliedTo) !== null && _a !== void 0 ? _a : [])
14
+ : [];
15
+ })),
16
+ ];
17
+ const scheduleIds = [
18
+ ...new Set(req.mutations.flatMap((m) => m.kind === 'merge' && m.objectKind === 'accessRule'
19
+ ? [
20
+ ...(m.props.permissions || []).map((p) => p.scheduleId),
21
+ ...(m.props.groupPermissions || []).map((p) => p.scheduleId),
22
+ ]
23
+ : [])),
24
+ ];
25
+ const notFoundPersonIds = personIds.filter((p) => !req.refMap['person'][p]);
26
+ const notFoundScheduleIds = scheduleIds.filter((s) => !req.refMap['schedule'][s]);
27
+ return [
28
+ ...notFoundPersonIds.map((id) => ({
29
+ code: 'NOT_FOUND',
30
+ objectId: id,
31
+ objectKind: 'person',
32
+ })),
33
+ ...notFoundScheduleIds.map((id) => ({
34
+ code: 'NOT_FOUND',
35
+ objectId: id,
36
+ objectKind: 'schedule',
37
+ })),
38
+ ];
39
+ };
40
+ const getBadReferenceIssues$ = (context, req) => {
41
+ if (!agent.find$)
42
+ return [];
43
+ const personIds = Object.entries(req.refMap['person'] || {}).flatMap(([objectId, refs]) => refs.map((ref) => ({ objectId, ref })));
44
+ const scheduleIds = Object.entries(req.refMap['schedule'] || {}).flatMap(([objectId, refs]) => refs.map((ref) => ({ objectId, ref })));
45
+ const ruleIds = Object.entries(req.refMap['accessRule'] || {}).flatMap(([objectId, refs]) => refs.map((ref) => ({ objectId, ref })));
46
+ const zoneIds = Object.entries(req.refMap['zone'] || {}).flatMap(([objectId, refs]) => refs.map((ref) => ({ objectId, ref })));
47
+ return (0, rxjs_1.forkJoin)([
48
+ // load persons
49
+ personIds.length < 1
50
+ ? (0, rxjs_1.of)(emptyMap)
51
+ : agent.find$(context, 'person', personIds.map((p) => p.ref)),
52
+ // load schedules
53
+ scheduleIds.length < 1
54
+ ? (0, rxjs_1.of)(emptyMap)
55
+ : agent.find$(context, 'schedule', scheduleIds.map((p) => p.ref)),
56
+ // load rules
57
+ ruleIds.length < 1
58
+ ? (0, rxjs_1.of)(emptyMap)
59
+ : agent.find$(context, 'accessRule', ruleIds.map((p) => p.ref)),
60
+ // load zones
61
+ zoneIds.length < 1
62
+ ? (0, rxjs_1.of)(emptyMap)
63
+ : agent.find$(context, 'zone', zoneIds.map((p) => p.ref)),
64
+ ]).pipe((0, rxjs_1.mergeMap)(([persons, schedules, rules, zones]) => {
65
+ var _a, _b;
66
+ const issues = [];
67
+ // check persons
68
+ for (const personId of personIds) {
69
+ if (!persons[personId.ref]) {
70
+ issues.push({
71
+ code: 'BAD_REFERENCE',
72
+ objectId: personId.objectId,
73
+ objectKind: 'person',
74
+ });
75
+ }
76
+ }
77
+ // check schedules
78
+ for (const scheduleId of scheduleIds) {
79
+ if (!schedules[scheduleId.ref]) {
80
+ issues.push({
81
+ code: 'BAD_REFERENCE',
82
+ objectId: scheduleId.objectId,
83
+ objectKind: 'schedule',
84
+ });
85
+ }
86
+ }
87
+ // check rules
88
+ for (const ruleId of ruleIds) {
89
+ if (!((_a = rules['accessRule']) === null || _a === void 0 ? void 0 : _a[ruleId.ref])) {
90
+ issues.push({
91
+ code: 'BAD_REFERENCE',
92
+ objectId: ruleId.ref,
93
+ objectKind: 'accessRule',
94
+ });
95
+ }
96
+ }
97
+ // check zones
98
+ for (const zoneId of zoneIds) {
99
+ if (!((_b = zones['zone']) === null || _b === void 0 ? void 0 : _b[zoneId.ref])) {
100
+ issues.push({
101
+ code: 'BAD_REFERENCE',
102
+ objectId: zoneId.objectId,
103
+ objectKind: 'zone',
104
+ });
105
+ }
106
+ }
107
+ return (0, rxjs_1.of)([
108
+ issues,
109
+ {
110
+ person: persons,
111
+ schedule: schedules,
112
+ accessRule: rules,
113
+ zone: zones,
114
+ },
115
+ ]);
116
+ }));
117
+ };
118
+ return (context, change) => {
119
+ return (0, rxjs_1.forkJoin)([
120
+ (0, rxjs_1.of)(getNotFoundIssues(change)),
121
+ getBadReferenceIssues$(context, change),
122
+ ]).pipe((0, rxjs_1.mergeMap)(([notFoundIssues, [badReferenceIssues, cache]]) => (0, rxjs_1.of)([
123
+ [...notFoundIssues, ...badReferenceIssues],
124
+ cache,
125
+ ])));
126
+ };
127
+ };
128
+ exports.createValidator = createValidator;
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awarevue/agent-sdk",
3
- "version": "1.0.30",
3
+ "version": "1.0.31",
4
4
  "description": "SDK for building Agent implementations that speak the Aware protocol.",
5
5
  "author": "Yaser Awajan",
6
6
  "license": "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awarevue/agent-sdk",
3
- "version": "1.0.30",
3
+ "version": "1.0.31",
4
4
  "description": "SDK for building Agent implementations that speak the Aware protocol.",
5
5
  "author": "Yaser Awajan",
6
6
  "license": "MIT",