mftsccs-node 0.2.19 → 0.2.21

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.
@@ -46,10 +46,12 @@ export interface BulkAccessRequest {
46
46
  }
47
47
  /**
48
48
  * Request model for bulk check access operations
49
+ * Mirrors C# BulkCheckAccessRequest
49
50
  */
50
51
  export interface BulkCheckAccessRequest {
51
- accessId: number;
52
- targets: BulkAccessTarget[];
52
+ accessIds: number[];
53
+ permission: string;
54
+ entityId?: number | null;
53
55
  }
54
56
  /**
55
57
  * Request model for access inheritance operations
@@ -65,6 +67,36 @@ export interface AccessInheritanceRequest {
65
67
  export interface SuperAdminRequest {
66
68
  accessId?: number | null;
67
69
  }
70
+ /**
71
+ * Request model for parent access inheritance operations
72
+ * Mirrors C# ParentAccessInheritanceRequest
73
+ */
74
+ export interface ParentAccessInheritanceRequest {
75
+ parentAccessId: number;
76
+ childAccessId?: number | null;
77
+ }
78
+ export interface ParentAccessInheritanceWithConceptRequest {
79
+ parentConceptId: number;
80
+ childConceptId?: number | null;
81
+ }
82
+ export interface BulkParentAccessInheritanceWithConceptRequest {
83
+ parentConceptId: number;
84
+ childConceptIds: number[];
85
+ }
86
+ export interface BulkParentAccessInheritanceResult {
87
+ childConceptId: number;
88
+ accessId: number;
89
+ success: boolean;
90
+ message?: string;
91
+ }
92
+ export interface SuperAdminWithConceptRequest {
93
+ conceptId: number;
94
+ }
95
+ export interface AccessInheritanceWithConceptRequest {
96
+ conceptId: number;
97
+ connectionTypeId?: number;
98
+ enable?: boolean;
99
+ }
68
100
  /**
69
101
  * Standard API response wrapper for access control endpoints
70
102
  */
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * This is the TypeScript equivalent of the C# APIClientService class.
8
8
  */
9
- import { AccessRequest, AccessResult, AccessControlAPIResponse, BulkAccessRequest, BulkCheckAccessRequest, AccessInheritanceRequest, SuperAdminRequest } from '../../DataStructures/AccessControl/AccessControlModels';
9
+ import { AccessRequest, AccessResult, AccessControlAPIResponse, BulkAccessRequest, BulkCheckAccessRequest, AccessInheritanceRequest, SuperAdminRequest, ParentAccessInheritanceRequest, ParentAccessInheritanceWithConceptRequest, BulkParentAccessInheritanceWithConceptRequest, BulkParentAccessInheritanceResult, SuperAdminWithConceptRequest, AccessInheritanceWithConceptRequest } from '../../DataStructures/AccessControl/AccessControlModels';
10
10
  export interface IAPIClientService {
11
11
  assignAccessAsync(request: AccessRequest): Promise<AccessControlAPIResponse<AccessResult>>;
12
12
  checkAccessAsync(request: AccessRequest): Promise<AccessControlAPIResponse<AccessResult>>;
@@ -20,6 +20,21 @@ export interface IAPIClientService {
20
20
  assignSuperAdminAccessAsync(request: SuperAdminRequest): Promise<AccessControlAPIResponse>;
21
21
  revokeSuperAdminAccessAsync(request: SuperAdminRequest): Promise<AccessControlAPIResponse>;
22
22
  checkSuperAdminStatusAsync(accessId: number): Promise<AccessControlAPIResponse>;
23
+ setParentAccessInheritanceAsync(request: ParentAccessInheritanceRequest): Promise<AccessControlAPIResponse>;
24
+ removeParentAccessInheritanceAsync(accessId: number, parentAccessId?: number): Promise<AccessControlAPIResponse>;
25
+ hasParentAccessInheritanceAsync(accessId: number, parentAccessId?: number): Promise<AccessControlAPIResponse>;
26
+ getParentAccessIdAsync(accessId: number): Promise<AccessControlAPIResponse>;
27
+ setParentAccessInheritanceByConceptAsync(request: ParentAccessInheritanceWithConceptRequest): Promise<AccessControlAPIResponse>;
28
+ setParentAccessInheritanceBulkByConceptAsync(request: BulkParentAccessInheritanceWithConceptRequest): Promise<AccessControlAPIResponse<BulkParentAccessInheritanceResult[]>>;
29
+ removeParentAccessInheritanceByConceptAsync(childConceptId: number, parentConceptId?: number): Promise<AccessControlAPIResponse>;
30
+ removeParentAccessInheritanceBulkByConceptAsync(request: BulkParentAccessInheritanceWithConceptRequest): Promise<AccessControlAPIResponse<BulkParentAccessInheritanceResult[]>>;
31
+ hasParentAccessInheritanceByConceptAsync(childConceptId: number, parentConceptId?: number): Promise<AccessControlAPIResponse>;
32
+ getParentAccessIdByConceptAsync(childConceptId: number): Promise<AccessControlAPIResponse>;
33
+ assignSuperAdminByConceptAsync(request: SuperAdminWithConceptRequest): Promise<AccessControlAPIResponse>;
34
+ revokeSuperAdminByConceptAsync(request: SuperAdminWithConceptRequest): Promise<AccessControlAPIResponse>;
35
+ checkSuperAdminByConceptAsync(conceptId: number): Promise<AccessControlAPIResponse>;
36
+ setAccessInheritanceByConceptAsync(request: AccessInheritanceWithConceptRequest): Promise<AccessControlAPIResponse>;
37
+ getAccessInheritanceStatusByConceptAsync(conceptId: number, connectionTypeId?: number): Promise<AccessControlAPIResponse>;
23
38
  }
24
39
  export declare class APIClientService implements IAPIClientService {
25
40
  private readonly baseUrl;
@@ -84,4 +99,64 @@ export declare class APIClientService implements IAPIClientService {
84
99
  * Check super admin status
85
100
  */
86
101
  checkSuperAdminStatusAsync(accessId: number): Promise<AccessControlAPIResponse>;
102
+ /**
103
+ * Set parent access inheritance link
104
+ */
105
+ setParentAccessInheritanceAsync(request: ParentAccessInheritanceRequest): Promise<AccessControlAPIResponse>;
106
+ /**
107
+ * Remove parent access inheritance link
108
+ */
109
+ removeParentAccessInheritanceAsync(accessId: number, parentAccessId?: number): Promise<AccessControlAPIResponse>;
110
+ /**
111
+ * Check if parent access inheritance link exists
112
+ */
113
+ hasParentAccessInheritanceAsync(accessId: number, parentAccessId?: number): Promise<AccessControlAPIResponse>;
114
+ /**
115
+ * Get the parent access ID for a given access ID
116
+ */
117
+ getParentAccessIdAsync(accessId: number): Promise<AccessControlAPIResponse>;
118
+ /**
119
+ * Set parent access inheritance by concept IDs (server resolves conceptId → accessId)
120
+ */
121
+ setParentAccessInheritanceByConceptAsync(request: ParentAccessInheritanceWithConceptRequest): Promise<AccessControlAPIResponse>;
122
+ /**
123
+ * Set parent access inheritance for multiple children with one parent (concept-based)
124
+ */
125
+ setParentAccessInheritanceBulkByConceptAsync(request: BulkParentAccessInheritanceWithConceptRequest): Promise<AccessControlAPIResponse<BulkParentAccessInheritanceResult[]>>;
126
+ /**
127
+ * Remove parent access inheritance by concept IDs
128
+ */
129
+ removeParentAccessInheritanceByConceptAsync(childConceptId: number, parentConceptId?: number): Promise<AccessControlAPIResponse>;
130
+ /**
131
+ * Remove parent access inheritance for multiple children (concept-based)
132
+ */
133
+ removeParentAccessInheritanceBulkByConceptAsync(request: BulkParentAccessInheritanceWithConceptRequest): Promise<AccessControlAPIResponse<BulkParentAccessInheritanceResult[]>>;
134
+ /**
135
+ * Check if parent access inheritance exists by concept IDs
136
+ */
137
+ hasParentAccessInheritanceByConceptAsync(childConceptId: number, parentConceptId?: number): Promise<AccessControlAPIResponse>;
138
+ /**
139
+ * Get the parent access ID by child concept ID
140
+ */
141
+ getParentAccessIdByConceptAsync(childConceptId: number): Promise<AccessControlAPIResponse>;
142
+ /**
143
+ * Assign super admin by concept ID
144
+ */
145
+ assignSuperAdminByConceptAsync(request: SuperAdminWithConceptRequest): Promise<AccessControlAPIResponse>;
146
+ /**
147
+ * Revoke super admin by concept ID
148
+ */
149
+ revokeSuperAdminByConceptAsync(request: SuperAdminWithConceptRequest): Promise<AccessControlAPIResponse>;
150
+ /**
151
+ * Check super admin status by concept ID
152
+ */
153
+ checkSuperAdminByConceptAsync(conceptId: number): Promise<AccessControlAPIResponse>;
154
+ /**
155
+ * Set access inheritance by concept ID
156
+ */
157
+ setAccessInheritanceByConceptAsync(request: AccessInheritanceWithConceptRequest): Promise<AccessControlAPIResponse>;
158
+ /**
159
+ * Get access inheritance status by concept ID
160
+ */
161
+ getAccessInheritanceStatusByConceptAsync(conceptId: number, connectionTypeId?: number): Promise<AccessControlAPIResponse>;
87
162
  }
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * CacheService
3
3
  *
4
- * Thread-safe in-memory cache for access checks.
4
+ * Thread-safe in-memory cache for access checks with TTL-based expiration.
5
5
  * Supports single and bulk queries with secondary indexes.
6
6
  * Key format: "{accessId}:{permission}:{entityId}"
7
- * Value: boolean (HasAccess)
7
+ * Value: CacheEntry { value: boolean, expiresAt: number }
8
8
  *
9
9
  * This is the TypeScript equivalent of the C# CacheService class.
10
10
  */
@@ -25,16 +25,17 @@ export declare class CacheService implements ICacheService {
25
25
  private readonly accessIndex;
26
26
  private readonly entityIndex;
27
27
  private static readonly superAdminCache;
28
+ private setCounter;
28
29
  /**
29
30
  * Generate a cache key from accessId, permission, and entityId
30
31
  */
31
32
  private generateKey;
32
33
  /**
33
- * Get cached access. Returns true/false if present, null if not cached.
34
+ * Get cached access. Returns true/false if present and not expired, null if not cached or expired.
34
35
  */
35
36
  get(accessId: number, permission: string, entityId?: number | null): boolean | null;
36
37
  /**
37
- * Set or update cached access
38
+ * Set or update cached access with TTL
38
39
  */
39
40
  set(accessId: number, permission: string, entityId: number | null | undefined, hasAccess: boolean): void;
40
41
  /**
@@ -46,25 +47,27 @@ export declare class CacheService implements ICacheService {
46
47
  */
47
48
  clear(): void;
48
49
  /**
49
- * Get all permissions for a specific accessId + entityId
50
+ * Sweep all expired entries from access cache, indexes, and super admin cache
51
+ */
52
+ private sweepExpired;
53
+ /**
54
+ * Get all permissions for a specific accessId + entityId (excludes expired entries)
50
55
  */
51
56
  getPermissionsByAccessAndEntity(accessId: number, entityId?: number | null): Map<string, boolean>;
52
57
  /**
53
- * Get all permissions for a specific accessId across all entities
54
- * Returns a Map with key tuple (entityId, permission) and value hasAccess
58
+ * Get all permissions for a specific accessId across all entities (excludes expired entries)
55
59
  */
56
60
  getPermissionsByAccess(accessId: number): Map<string, boolean>;
57
61
  /**
58
- * Get all permissions for a specific entity across all accessIds
59
- * Returns a Map with key tuple (accessId, permission) and value hasAccess
62
+ * Get all permissions for a specific entity across all accessIds (excludes expired entries)
60
63
  */
61
64
  getPermissionsByEntity(entityId: number): Map<string, boolean>;
62
65
  /**
63
- * Get cached super admin status for an entity
66
+ * Get cached super admin status for an entity (returns null if expired or not cached)
64
67
  */
65
68
  getSuperAdmin(entityId: number): boolean | null;
66
69
  /**
67
- * Set super admin status for an entity
70
+ * Set super admin status for an entity with TTL
68
71
  */
69
72
  setSuperAdmin(entityId: number, isSuperAdmin: boolean): void;
70
73
  /**
@@ -2,24 +2,24 @@
2
2
  * AccessControlService
3
3
  *
4
4
  * This service provides access control functionality including:
5
- * - Check access for concepts with complex permission logic
5
+ * - 5-phase bulk access check with BFS inheritance graph traversal
6
6
  * - Assign and revoke access permissions
7
7
  * - Bulk operations for access management
8
8
  * - Super admin checks with caching
9
- * - Access inheritance management
9
+ * - Access inheritance management (including parent access inheritance)
10
10
  *
11
- * This is the TypeScript equivalent of the C# AccessControlService class.
11
+ * This is the TypeScript equivalent of the C# AccessControlService class (v3.4.0).
12
12
  * All methods are static and can be called directly on the class.
13
13
  */
14
- import { AccessResult, BulkAccessRequest } from '../../DataStructures/AccessControl/AccessControlModels';
14
+ import { AccessResult, BulkAccessRequest, BulkParentAccessInheritanceResult } from '../../DataStructures/AccessControl/AccessControlModels';
15
15
  import { PermissionSet } from './PermissionSet';
16
16
  export declare class AccessControlService {
17
17
  private static cacheService;
18
18
  private static apiClient;
19
19
  private static initialize;
20
20
  /**
21
- * Check whether a user/entity has the specified permission.
22
- * Returns true if allowed, false otherwise.
21
+ * Check whether a user/entity has the specified permission on a single concept.
22
+ * Delegates to checkAccessBulk for full inheritance + group resolution.
23
23
  *
24
24
  * @param conceptId - The ID of the concept to check access for
25
25
  * @param permission - The permission to check (PermissionSet flags)
@@ -27,9 +27,25 @@ export declare class AccessControlService {
27
27
  * @returns Promise<boolean> - True if access is granted, false otherwise
28
28
  */
29
29
  static checkAccess(conceptId: number, permission: PermissionSet, entityId?: number | null): Promise<boolean>;
30
+ /**
31
+ * 5-phase bulk access check algorithm.
32
+ * Matches the C# AccessControlService.CheckAccessBulk implementation.
33
+ *
34
+ * Phase 1: Super-admin short-circuit
35
+ * Phase 2: Fast-path classification (owner, public, type concepts)
36
+ * Phase 3: BFS inheritance graph resolution (3 sources)
37
+ * Phase 4: Bulk access decision resolution (cache + API)
38
+ * Phase 5: Grant-only merge per concept
39
+ *
40
+ * @param conceptIds - List of concept IDs to check
41
+ * @param permission - The permission to check (PermissionSet flags)
42
+ * @param entityId - Optional entity ID
43
+ * @returns Promise<Map<number, boolean>> - conceptId → hasAccess
44
+ */
45
+ static checkAccessBulk(conceptIds: number[], permission: PermissionSet, entityId?: number | null): Promise<Map<number, boolean>>;
30
46
  /**
31
47
  * Get all conceptIds which have a certain permission for an entity.
32
- * Optional filter by a list of conceptIds.
48
+ * Delegates to checkAccessBulk for full inheritance support.
33
49
  *
34
50
  * @param permission - The permission to check (PermissionSet flags)
35
51
  * @param conceptIdsFilter - List of concept IDs to filter
@@ -37,6 +53,32 @@ export declare class AccessControlService {
37
53
  * @returns Promise<number[]> - Array of concept IDs that have the permission
38
54
  */
39
55
  static getConceptIdsWithPermission(permission: PermissionSet, conceptIdsFilter: number[], entityId?: number | null): Promise<number[]>;
56
+ /**
57
+ * Resolve inheritance graph via 3-source BFS, depth-limited to MAX_BFS_DEPTH.
58
+ *
59
+ * Source 1: FreeSchema internal connections ("the_parent_access_inheritance")
60
+ * Source 2: Explicit parent access links (via Access API)
61
+ * Source 3: Concept-connection access inheritance
62
+ *
63
+ * @returns Map<number, number[]> — accessId → [self, parent1, grandparent1, ...]
64
+ */
65
+ private static resolveBulkInheritanceGraph;
66
+ /**
67
+ * Resolve access decisions for all (accessId × subject) combinations.
68
+ * Probes cache first, then makes bulk API calls for misses.
69
+ *
70
+ * @returns Map with key "accessId:subjectId" → hasAccess
71
+ */
72
+ private static resolveBulkDecisions;
73
+ /**
74
+ * Resolve all subjects for an entity: [null, entityId, ...groupIds]
75
+ */
76
+ private static resolveSubjects;
77
+ /**
78
+ * Check if any grant exists across own chain + type chain for any subject.
79
+ * Grant-only model: any grant → ALLOW, no grants → DENY.
80
+ */
81
+ private static hasAnyGrant;
40
82
  /**
41
83
  * Assign access permission to an entity
42
84
  *
@@ -93,6 +135,53 @@ export declare class AccessControlService {
93
135
  * @returns Promise<boolean> - True if successful, false otherwise
94
136
  */
95
137
  static setAccessInheritanceStatus(conceptId: number, isEnabled: boolean, connectionTypeId?: number): Promise<boolean>;
138
+ /**
139
+ * Set parent access inheritance link for a concept
140
+ *
141
+ * @param conceptId - The child concept ID
142
+ * @param parentConceptId - The parent concept ID to inherit from
143
+ * @returns Promise<number> - The new access ID, or existing access ID
144
+ */
145
+ static setParentAccessInheritance(conceptId: number, parentConceptId: number): Promise<number>;
146
+ /**
147
+ * Remove parent access inheritance link
148
+ *
149
+ * @param conceptId - The child concept ID
150
+ * @param parentConceptId - Optional parent concept ID (removes specific link or all)
151
+ * @returns Promise<string> - Status message
152
+ */
153
+ static removeParentAccessInheritance(conceptId: number, parentConceptId?: number): Promise<string>;
154
+ /**
155
+ * Check if parent access inheritance link exists
156
+ *
157
+ * @param conceptId - The child concept ID
158
+ * @param parentConceptId - Optional parent concept ID to check specific link
159
+ * @returns Promise<boolean> - True if link exists
160
+ */
161
+ static hasParentAccessInheritance(conceptId: number, parentConceptId?: number): Promise<boolean>;
162
+ /**
163
+ * Get the parent access ID for a concept
164
+ *
165
+ * @param conceptId - The child concept ID
166
+ * @returns Promise<number | null> - Parent access ID or null
167
+ */
168
+ static getParentAccessId(conceptId: number): Promise<number | null>;
169
+ /**
170
+ * Set parent access inheritance for multiple children with one parent
171
+ *
172
+ * @param childConceptIds - List of child concept IDs
173
+ * @param parentConceptId - The parent concept ID to inherit from
174
+ * @returns Promise<BulkParentAccessInheritanceResult[]> - Results per child
175
+ */
176
+ static setParentAccessInheritanceBulk(childConceptIds: number[], parentConceptId: number): Promise<BulkParentAccessInheritanceResult[]>;
177
+ /**
178
+ * Remove parent access inheritance for multiple children
179
+ *
180
+ * @param childConceptIds - List of child concept IDs
181
+ * @param parentConceptId - Optional parent concept ID
182
+ * @returns Promise<BulkParentAccessInheritanceResult[]> - Results per child
183
+ */
184
+ static removeParentAccessInheritanceBulk(childConceptIds: number[], parentConceptId?: number): Promise<BulkParentAccessInheritanceResult[]>;
96
185
  /**
97
186
  * Check if an entity is a super admin
98
187
  * Uses caching for performance
@@ -116,19 +205,21 @@ export declare class AccessControlService {
116
205
  */
117
206
  static revokeSuperAdmin(entityId: number): Promise<string>;
118
207
  /**
119
- * Convert PermissionSet to string for API calls
208
+ * Parse boolean from API response data.
209
+ * Handles: raw boolean, string, object with known property names.
210
+ * Matches C# ParseBoolData helper.
120
211
  */
121
- private static permissionSetToString;
212
+ private static parseBoolData;
122
213
  /**
123
- * Internal method to check access via cache or API
124
- *
125
- * @param accessId - The access ID to check
126
- * @param permission - The permission to check (string)
127
- * @param entityId - Optional entity ID
128
- * @returns Promise<boolean> - True if access is granted, false otherwise
214
+ * Parse integer from API response data.
215
+ * Handles: raw number, string, object with known property names.
216
+ * Matches C# ParseIntData helper.
129
217
  */
130
- private static checkAccessInternal;
131
- private static checkGroupAccessInternal;
218
+ private static parseIntData;
219
+ /**
220
+ * Convert PermissionSet to string for API calls
221
+ */
222
+ private static permissionSetToString;
132
223
  /**
133
224
  * Clear all access cache entries
134
225
  */
@@ -12,4 +12,4 @@ export { AccessControlService } from './AccessControlService';
12
12
  export { CacheService, ICacheService } from './AccessControlCacheService';
13
13
  export { APIClientService, IAPIClientService } from './APIClientService';
14
14
  export { PermissionSet, getPermissionSetFromStrings, getStringsFromPermissionSet, isValidPermission } from './PermissionSet';
15
- export { PermissionSet as PermissionSetEnum, AccessRequest, AccessResult, BulkAccessRequest, BulkAccessTarget, BulkCheckAccessRequest, AccessInheritanceRequest, SuperAdminRequest, AccessControlAPIResponse, AccessControlApiResponse, AddAccessByEntityRequest, AddPublicAccessToConcept, AddAccessByEntityBulkRequest, AddAccessByUserRequest, CheckAccessBulk, VALID_PERMISSIONS, isValidPermission as isValidPermissionFromModels } from '../../DataStructures/AccessControl/AccessControlModels';
15
+ export { PermissionSet as PermissionSetEnum, AccessRequest, AccessResult, BulkAccessRequest, BulkAccessTarget, BulkCheckAccessRequest, AccessInheritanceRequest, SuperAdminRequest, AccessControlAPIResponse, AccessControlApiResponse, AddAccessByEntityRequest, AddPublicAccessToConcept, AddAccessByEntityBulkRequest, AddAccessByUserRequest, CheckAccessBulk, ParentAccessInheritanceRequest, VALID_PERMISSIONS, isValidPermission as isValidPermissionFromModels } from '../../DataStructures/AccessControl/AccessControlModels';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mftsccs-node",
3
- "version": "0.2.19",
3
+ "version": "0.2.21",
4
4
  "environment": "production",
5
5
  "description": "Full Pack of concept and connection system",
6
6
  "main": "dist/bundle.js",