@memberjunction/core-entities 5.24.0 → 5.25.0

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.
Files changed (33) hide show
  1. package/dist/engines/FileStorageEngine.d.ts +21 -5
  2. package/dist/engines/FileStorageEngine.d.ts.map +1 -1
  3. package/dist/engines/FileStorageEngine.js +24 -4
  4. package/dist/engines/FileStorageEngine.js.map +1 -1
  5. package/dist/engines/GeoDataEngine.d.ts +141 -0
  6. package/dist/engines/GeoDataEngine.d.ts.map +1 -0
  7. package/dist/engines/GeoDataEngine.js +425 -0
  8. package/dist/engines/GeoDataEngine.js.map +1 -0
  9. package/dist/engines/InstanceConfigEngine.d.ts +105 -0
  10. package/dist/engines/InstanceConfigEngine.d.ts.map +1 -0
  11. package/dist/engines/InstanceConfigEngine.js +198 -0
  12. package/dist/engines/InstanceConfigEngine.js.map +1 -0
  13. package/dist/engines/SearchEngineBase.d.ts +76 -0
  14. package/dist/engines/SearchEngineBase.d.ts.map +1 -0
  15. package/dist/engines/SearchEngineBase.js +141 -0
  16. package/dist/engines/SearchEngineBase.js.map +1 -0
  17. package/dist/engines/UserInfoEngine.d.ts +15 -1
  18. package/dist/engines/UserInfoEngine.d.ts.map +1 -1
  19. package/dist/engines/UserInfoEngine.js +45 -0
  20. package/dist/engines/UserInfoEngine.js.map +1 -1
  21. package/dist/engines/artifacts.d.ts +13 -0
  22. package/dist/engines/artifacts.d.ts.map +1 -1
  23. package/dist/engines/artifacts.js +25 -0
  24. package/dist/engines/artifacts.js.map +1 -1
  25. package/dist/generated/entity_subclasses.d.ts +1629 -71
  26. package/dist/generated/entity_subclasses.d.ts.map +1 -1
  27. package/dist/generated/entity_subclasses.js +2438 -123
  28. package/dist/generated/entity_subclasses.js.map +1 -1
  29. package/dist/index.d.ts +3 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +3 -0
  32. package/dist/index.js.map +1 -1
  33. package/package.json +5 -5
@@ -0,0 +1,198 @@
1
+ import { BaseEngine } from "@memberjunction/core";
2
+ /**
3
+ * InstanceConfigEngine provides centralized, cached access to instance-level feature configuration.
4
+ * It loads all MJ: Instance Configurations records into memory and provides typed getters
5
+ * for boolean, number, string, and JSON values by FeatureKey.
6
+ *
7
+ * Uses BaseEngine for automatic caching and entity-event-based auto-refresh so that
8
+ * configuration changes are reflected without requiring a manual reload.
9
+ *
10
+ * Usage:
11
+ * ```typescript
12
+ * const engine = InstanceConfigEngine.Instance;
13
+ * await engine.Config(false, contextUser);
14
+ *
15
+ * // Read a boolean flag
16
+ * const searchEnabled = engine.GetBoolean('Shell.SearchBar.Enabled');
17
+ *
18
+ * // Read a number with a custom default
19
+ * const maxResults = engine.GetNumber('Search.MaxResults', 50);
20
+ *
21
+ * // Read a JSON object
22
+ * const uiConfig = engine.GetJSON<{ theme: string }>('UI.DefaultConfig');
23
+ *
24
+ * // Admin: update a setting
25
+ * await engine.Set('Shell.SearchBar.Enabled', 'true', contextUser);
26
+ * ```
27
+ */
28
+ export class InstanceConfigEngine extends BaseEngine {
29
+ constructor() {
30
+ super(...arguments);
31
+ this._configs = [];
32
+ }
33
+ /**
34
+ * Returns the global instance of the class. This is a singleton class, so there
35
+ * is only one instance of it in the application. Do not directly create new instances
36
+ * of it, always use this method to get the instance.
37
+ */
38
+ static get Instance() {
39
+ return super.getInstance();
40
+ }
41
+ /**
42
+ * Configures the engine by loading all instance configuration records from the database.
43
+ * @param forceRefresh - If true, forces a refresh from the database even if data is cached
44
+ * @param contextUser - Optional user context for server-side operations
45
+ * @param provider - Optional metadata provider
46
+ */
47
+ async Config(forceRefresh, contextUser, provider) {
48
+ const configs = [
49
+ {
50
+ Type: 'entity',
51
+ EntityName: 'MJ: Instance Configurations',
52
+ PropertyName: '_configs',
53
+ CacheLocal: true
54
+ }
55
+ ];
56
+ await this.Load(configs, provider, forceRefresh, contextUser);
57
+ }
58
+ // ================================================================
59
+ // Cached data getter
60
+ // ================================================================
61
+ /** All instance configuration records */
62
+ get InstanceConfigs() {
63
+ return this._configs || [];
64
+ }
65
+ // ================================================================
66
+ // Lookup helpers
67
+ // ================================================================
68
+ /**
69
+ * Find a configuration record by its FeatureKey.
70
+ * @param featureKey - The dot-notation feature key (e.g. 'Shell.SearchBar.Enabled')
71
+ * @returns The configuration entity, or undefined if not found
72
+ */
73
+ GetConfigByKey(featureKey) {
74
+ if (!featureKey)
75
+ return undefined;
76
+ return this._configs.find(c => c.FeatureKey === featureKey);
77
+ }
78
+ /**
79
+ * Get all configuration records for a given category.
80
+ * @param category - The category to filter by (e.g. 'General', 'Search')
81
+ * @returns Array of matching configuration entities
82
+ */
83
+ GetConfigsByCategory(category) {
84
+ if (!category)
85
+ return [];
86
+ const lower = category.trim().toLowerCase();
87
+ return this._configs.filter(c => c.Category?.trim().toLowerCase() === lower);
88
+ }
89
+ // ================================================================
90
+ // Typed value getters
91
+ // ================================================================
92
+ /**
93
+ * Get the raw string value for a feature key. Returns the record's Value if non-empty,
94
+ * otherwise falls back to DefaultValue, then to undefined.
95
+ * @param featureKey - The dot-notation feature key
96
+ * @returns The value string, or undefined if the key is not found
97
+ */
98
+ Get(featureKey) {
99
+ const config = this.GetConfigByKey(featureKey);
100
+ if (!config)
101
+ return undefined;
102
+ return this.ResolveValue(config);
103
+ }
104
+ /**
105
+ * Get a boolean value for a feature key. Interprets 'true' (case-insensitive) as true,
106
+ * everything else as false. Returns the provided default if the key is not found.
107
+ * @param featureKey - The dot-notation feature key
108
+ * @param defaultValue - Value to return if the key is not found (defaults to true)
109
+ */
110
+ GetBoolean(featureKey, defaultValue = true) {
111
+ const raw = this.Get(featureKey);
112
+ if (raw === undefined)
113
+ return defaultValue;
114
+ return raw.trim().toLowerCase() === 'true';
115
+ }
116
+ /**
117
+ * Get a numeric value for a feature key. Returns the provided default if the key
118
+ * is not found or the value cannot be parsed as a number.
119
+ * @param featureKey - The dot-notation feature key
120
+ * @param defaultValue - Value to return if the key is not found or unparseable (defaults to 0)
121
+ */
122
+ GetNumber(featureKey, defaultValue = 0) {
123
+ const raw = this.Get(featureKey);
124
+ if (raw === undefined)
125
+ return defaultValue;
126
+ const parsed = Number(raw);
127
+ return Number.isNaN(parsed) ? defaultValue : parsed;
128
+ }
129
+ /**
130
+ * Get a JSON-parsed value for a feature key. Returns the provided default if the key
131
+ * is not found or the value cannot be parsed as JSON.
132
+ * @param featureKey - The dot-notation feature key
133
+ * @param defaultValue - Value to return if the key is not found or unparseable
134
+ */
135
+ GetJSON(featureKey, defaultValue) {
136
+ const raw = this.Get(featureKey);
137
+ if (raw === undefined)
138
+ return defaultValue;
139
+ try {
140
+ return JSON.parse(raw);
141
+ }
142
+ catch {
143
+ return defaultValue;
144
+ }
145
+ }
146
+ // ================================================================
147
+ // Admin setter
148
+ // ================================================================
149
+ /**
150
+ * Update the Value of an existing configuration record. This method updates the
151
+ * record in the database and refreshes the local cache entry.
152
+ *
153
+ * Note: This only updates existing records. To create new configuration entries,
154
+ * use the standard entity creation workflow.
155
+ *
156
+ * @param featureKey - The dot-notation feature key to update
157
+ * @param value - The new value string
158
+ * @param contextUser - Optional user context (required on server-side)
159
+ * @returns true if the save succeeded, false otherwise
160
+ */
161
+ async Set(featureKey, value, contextUser) {
162
+ const config = this.GetConfigByKey(featureKey);
163
+ if (!config) {
164
+ console.error(`InstanceConfigEngine.Set: FeatureKey '${featureKey}' not found`);
165
+ return false;
166
+ }
167
+ try {
168
+ config.Value = value;
169
+ const saved = await config.Save();
170
+ if (saved) {
171
+ return true;
172
+ }
173
+ else {
174
+ console.error('InstanceConfigEngine.Set: Failed to save:', config.LatestResult?.Message);
175
+ return false;
176
+ }
177
+ }
178
+ catch (error) {
179
+ console.error('InstanceConfigEngine.Set: Error:', error instanceof Error ? error.message : String(error));
180
+ return false;
181
+ }
182
+ }
183
+ // ================================================================
184
+ // Private helpers
185
+ // ================================================================
186
+ /**
187
+ * Resolve the effective value for a configuration record. Returns Value if
188
+ * it is non-empty, otherwise falls back to DefaultValue.
189
+ */
190
+ ResolveValue(config) {
191
+ const val = config.Value;
192
+ if (val != null && val.trim().length > 0) {
193
+ return val;
194
+ }
195
+ return config.DefaultValue;
196
+ }
197
+ }
198
+ //# sourceMappingURL=InstanceConfigEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InstanceConfigEngine.js","sourceRoot":"","sources":["../../src/engines/InstanceConfigEngine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ import { BaseEngine, IMetadataProvider, UserInfo } from "@memberjunction/core";
2
+ import { MJSearchProviderEntity } from "../generated/entity_subclasses.js";
3
+ /**
4
+ * SearchEngineBase provides cached access to SearchProvider metadata.
5
+ * Loads all MJ: Search Providers records via BaseEngine and provides
6
+ * typed getters and lookups for use anywhere (client or server).
7
+ *
8
+ * The server-side SearchEngine class uses SearchEngineBase.Instance to
9
+ * access cached provider metadata instead of loading directly via RunView.
10
+ *
11
+ * Uses BaseEngine for automatic caching and entity-event-based auto-refresh
12
+ * so that provider configuration changes are reflected without manual reload.
13
+ *
14
+ * Usage:
15
+ * ```typescript
16
+ * const base = SearchEngineBase.Instance;
17
+ * await base.Config(false, contextUser);
18
+ *
19
+ * // Get all active providers
20
+ * const activeProviders = base.ActiveProviders;
21
+ *
22
+ * // Find a provider by driver class
23
+ * const vectorProvider = base.GetProviderByDriverClass('VectorSearchProvider');
24
+ * ```
25
+ */
26
+ export declare class SearchEngineBase extends BaseEngine<SearchEngineBase> {
27
+ /**
28
+ * Returns the global singleton instance.
29
+ */
30
+ static get Instance(): SearchEngineBase;
31
+ private _providers;
32
+ /**
33
+ * Configures the engine by loading all search provider records from the database.
34
+ * @param forceRefresh - If true, forces a refresh from the database even if data is cached
35
+ * @param contextUser - Optional user context for server-side operations
36
+ * @param provider - Optional metadata provider
37
+ */
38
+ Config(forceRefresh?: boolean, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<void>;
39
+ /** All search provider records (any status) */
40
+ get Providers(): MJSearchProviderEntity[];
41
+ /** Only active search providers, sorted by Priority ascending */
42
+ get ActiveProviders(): MJSearchProviderEntity[];
43
+ /** Active providers that support preview/autocomplete searches */
44
+ get PreviewProviders(): MJSearchProviderEntity[];
45
+ /**
46
+ * Find a provider by its DriverClass key.
47
+ * @param driverClass - The DriverClass value (e.g., 'VectorSearchProvider')
48
+ * @returns The provider entity, or undefined if not found
49
+ */
50
+ GetProviderByDriverClass(driverClass: string): MJSearchProviderEntity | undefined;
51
+ /**
52
+ * Find a provider by its Name.
53
+ * @param name - The provider name (e.g., 'Semantic')
54
+ * @returns The provider entity, or undefined if not found
55
+ */
56
+ GetProviderByName(name: string): MJSearchProviderEntity | undefined;
57
+ /**
58
+ * Find a provider by its ID.
59
+ * @param id - The provider record ID
60
+ * @returns The provider entity, or undefined if not found
61
+ */
62
+ GetProviderById(id: string): MJSearchProviderEntity | undefined;
63
+ /**
64
+ * Get the display label for a source type, resolving from provider metadata.
65
+ * Falls back to the source type string if no provider matches.
66
+ * @param sourceType - The source type key (e.g., 'vector', 'entity')
67
+ */
68
+ GetDisplayNameForSourceType(sourceType: string): string;
69
+ /**
70
+ * Get the icon for a source type, resolving from provider metadata.
71
+ * Falls back to a generic icon if no provider matches.
72
+ * @param sourceType - The source type key (e.g., 'vector', 'entity')
73
+ */
74
+ GetIconForSourceType(sourceType: string): string;
75
+ }
76
+ //# sourceMappingURL=SearchEngineBase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchEngineBase.d.ts","sourceRoot":"","sources":["../../src/engines/SearchEngineBase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA4B,iBAAiB,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGzG,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBACa,gBAAiB,SAAQ,UAAU,CAAC,gBAAgB,CAAC;IAC9D;;OAEG;IACH,WAAkB,QAAQ,IAAI,gBAAgB,CAE7C;IAED,OAAO,CAAC,UAAU,CAAgC;IAElD;;;;;OAKG;IACU,MAAM,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBhH,+CAA+C;IAC/C,IAAW,SAAS,IAAI,sBAAsB,EAAE,CAE/C;IAED,iEAAiE;IACjE,IAAW,eAAe,IAAI,sBAAsB,EAAE,CAIrD;IAED,kEAAkE;IAClE,IAAW,gBAAgB,IAAI,sBAAsB,EAAE,CAEtD;IAMD;;;;OAIG;IACI,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS;IAKxF;;;;OAIG;IACI,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS;IAM1E;;;;OAIG;IACI,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS;IAKtE;;;;OAIG;IACI,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAQ9D;;;;OAIG;IACI,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;CAO1D"}
@@ -0,0 +1,141 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { BaseEngine } from "@memberjunction/core";
8
+ import { RegisterForStartup } from "@memberjunction/core";
9
+ import { UUIDsEqual } from "@memberjunction/global";
10
+ /**
11
+ * SearchEngineBase provides cached access to SearchProvider metadata.
12
+ * Loads all MJ: Search Providers records via BaseEngine and provides
13
+ * typed getters and lookups for use anywhere (client or server).
14
+ *
15
+ * The server-side SearchEngine class uses SearchEngineBase.Instance to
16
+ * access cached provider metadata instead of loading directly via RunView.
17
+ *
18
+ * Uses BaseEngine for automatic caching and entity-event-based auto-refresh
19
+ * so that provider configuration changes are reflected without manual reload.
20
+ *
21
+ * Usage:
22
+ * ```typescript
23
+ * const base = SearchEngineBase.Instance;
24
+ * await base.Config(false, contextUser);
25
+ *
26
+ * // Get all active providers
27
+ * const activeProviders = base.ActiveProviders;
28
+ *
29
+ * // Find a provider by driver class
30
+ * const vectorProvider = base.GetProviderByDriverClass('VectorSearchProvider');
31
+ * ```
32
+ */
33
+ let SearchEngineBase = class SearchEngineBase extends BaseEngine {
34
+ constructor() {
35
+ super(...arguments);
36
+ this._providers = [];
37
+ }
38
+ /**
39
+ * Returns the global singleton instance.
40
+ */
41
+ static get Instance() {
42
+ return super.getInstance();
43
+ }
44
+ /**
45
+ * Configures the engine by loading all search provider records from the database.
46
+ * @param forceRefresh - If true, forces a refresh from the database even if data is cached
47
+ * @param contextUser - Optional user context for server-side operations
48
+ * @param provider - Optional metadata provider
49
+ */
50
+ async Config(forceRefresh, contextUser, provider) {
51
+ const configs = [
52
+ {
53
+ Type: 'entity',
54
+ EntityName: 'MJ: Search Providers',
55
+ PropertyName: '_providers',
56
+ CacheLocal: true,
57
+ }
58
+ ];
59
+ await this.Load(configs, provider, forceRefresh, contextUser);
60
+ }
61
+ // ================================================================
62
+ // Cached data getters
63
+ // ================================================================
64
+ /** All search provider records (any status) */
65
+ get Providers() {
66
+ return this._providers || [];
67
+ }
68
+ /** Only active search providers, sorted by Priority ascending */
69
+ get ActiveProviders() {
70
+ return this.Providers
71
+ .filter(p => p.Status === 'Active')
72
+ .sort((a, b) => a.Priority - b.Priority);
73
+ }
74
+ /** Active providers that support preview/autocomplete searches */
75
+ get PreviewProviders() {
76
+ return this.ActiveProviders.filter(p => p.SupportsPreview);
77
+ }
78
+ // ================================================================
79
+ // Lookup helpers
80
+ // ================================================================
81
+ /**
82
+ * Find a provider by its DriverClass key.
83
+ * @param driverClass - The DriverClass value (e.g., 'VectorSearchProvider')
84
+ * @returns The provider entity, or undefined if not found
85
+ */
86
+ GetProviderByDriverClass(driverClass) {
87
+ if (!driverClass)
88
+ return undefined;
89
+ return this._providers.find(p => p.DriverClass === driverClass);
90
+ }
91
+ /**
92
+ * Find a provider by its Name.
93
+ * @param name - The provider name (e.g., 'Semantic')
94
+ * @returns The provider entity, or undefined if not found
95
+ */
96
+ GetProviderByName(name) {
97
+ if (!name)
98
+ return undefined;
99
+ const lower = name.trim().toLowerCase();
100
+ return this._providers.find(p => p.Name.trim().toLowerCase() === lower);
101
+ }
102
+ /**
103
+ * Find a provider by its ID.
104
+ * @param id - The provider record ID
105
+ * @returns The provider entity, or undefined if not found
106
+ */
107
+ GetProviderById(id) {
108
+ if (!id)
109
+ return undefined;
110
+ return this._providers.find(p => UUIDsEqual(p.ID, id));
111
+ }
112
+ /**
113
+ * Get the display label for a source type, resolving from provider metadata.
114
+ * Falls back to the source type string if no provider matches.
115
+ * @param sourceType - The source type key (e.g., 'vector', 'entity')
116
+ */
117
+ GetDisplayNameForSourceType(sourceType) {
118
+ const provider = this.ActiveProviders.find(p => {
119
+ const driverLower = p.DriverClass.toLowerCase();
120
+ return driverLower.startsWith(sourceType.toLowerCase());
121
+ });
122
+ return provider?.DisplayName ?? provider?.Name ?? sourceType;
123
+ }
124
+ /**
125
+ * Get the icon for a source type, resolving from provider metadata.
126
+ * Falls back to a generic icon if no provider matches.
127
+ * @param sourceType - The source type key (e.g., 'vector', 'entity')
128
+ */
129
+ GetIconForSourceType(sourceType) {
130
+ const provider = this.ActiveProviders.find(p => {
131
+ const driverLower = p.DriverClass.toLowerCase();
132
+ return driverLower.startsWith(sourceType.toLowerCase());
133
+ });
134
+ return provider?.Icon ?? 'fa-solid fa-circle';
135
+ }
136
+ };
137
+ SearchEngineBase = __decorate([
138
+ RegisterForStartup()
139
+ ], SearchEngineBase);
140
+ export { SearchEngineBase };
141
+ //# sourceMappingURL=SearchEngineBase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchEngineBase.js","sourceRoot":"","sources":["../../src/engines/SearchEngineBase.ts"],"names":[],"mappings":"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"}
@@ -4,8 +4,9 @@ import { ApplicationInfo, BaseEngine, IMetadataProvider, UserInfo } from '@membe
4
4
  * - 'installed_active': User has UserApplication record with IsActive=true
5
5
  * - 'installed_inactive': User has UserApplication record with IsActive=false
6
6
  * - 'not_installed': User has no UserApplication record for this app
7
+ * - 'not_authorized': User's roles do not grant access to the application
7
8
  */
8
- export type UserApplicationAccessStatus = 'installed_active' | 'installed_inactive' | 'not_installed';
9
+ export type UserApplicationAccessStatus = 'installed_active' | 'installed_inactive' | 'not_installed' | 'not_authorized';
9
10
  import { MJUserNotificationEntity, MJUserNotificationTypeEntity, MJWorkspaceEntity, MJUserApplicationEntity, MJUserFavoriteEntity, MJUserRecordLogEntity, MJUserSettingEntity, MJUserNotificationPreferenceEntity } from '../generated/entity_subclasses.js';
10
11
  /**
11
12
  * UserInfoEngine is a singleton engine that provides centralized access to user-specific data
@@ -42,6 +43,7 @@ export declare class UserInfoEngine extends BaseEngine<UserInfoEngine> {
42
43
  private _UserSettings;
43
44
  private _NotificationTypes;
44
45
  private _UserNotificationPreferences;
46
+ private _applicationRoles;
45
47
  private _loadedForUserId;
46
48
  private _createDefaultAppsPromise;
47
49
  /**
@@ -231,10 +233,22 @@ export declare class UserInfoEngine extends BaseEngine<UserInfoEngine> {
231
233
  get LoadedForUserId(): string | null;
232
234
  /**
233
235
  * Check the user's access status for an application.
236
+ * First checks role-based authorization (ApplicationRole records), then installation status.
234
237
  * @param applicationId - The application ID to check
235
238
  * @returns The user's access status for this application
236
239
  */
237
240
  CheckUserApplicationAccess(applicationId: string): UserApplicationAccessStatus;
241
+ /**
242
+ * Checks if the current user's roles grant access to the application.
243
+ * If no ApplicationRole records exist for the app, access is open (backwards compatible).
244
+ * If records exist, user must have at least one role with CanAccess=1.
245
+ */
246
+ UserHasApplicationAccess(applicationId: string): boolean;
247
+ /**
248
+ * Checks if the current user can administer a specific application.
249
+ * Requires an explicit ApplicationRole record with CanAdmin=1.
250
+ */
251
+ UserCanAdminApplication(applicationId: string): boolean;
238
252
  /**
239
253
  * Check if an application is inactive in the system metadata.
240
254
  * @param applicationId - The application ID to check
@@ -1 +1 @@
1
- {"version":3,"file":"UserInfoEngine.d.ts","sourceRoot":"","sources":["../../src/engines/UserInfoEngine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"UserInfoEngine.d.ts","sourceRoot":"","sources":["../../src/engines/UserInfoEngine.ts"],"names":[],"mappings":"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"}
@@ -41,6 +41,8 @@ let UserInfoEngine = class UserInfoEngine extends BaseEngine {
41
41
  this._NotificationTypes = [];
42
42
  // User notification preferences (user-specific)
43
43
  this._UserNotificationPreferences = [];
44
+ // Application role assignments (global - not user-specific)
45
+ this._applicationRoles = [];
44
46
  // Track the user ID we loaded data for
45
47
  this._loadedForUserId = null;
46
48
  // Track in-progress CreateDefaultApplications call to prevent duplicate execution
@@ -148,6 +150,12 @@ let UserInfoEngine = class UserInfoEngine extends BaseEngine {
148
150
  PropertyName: '_UserNotificationPreferences',
149
151
  CacheLocal: true,
150
152
  },
153
+ {
154
+ Type: 'entity',
155
+ EntityName: 'MJ: Application Roles',
156
+ PropertyName: '_applicationRoles',
157
+ CacheLocal: true,
158
+ },
151
159
  ];
152
160
  await super.Load(configs, provider, forceRefresh, contextUser);
153
161
  this._loadedForUserId = userId;
@@ -536,16 +544,53 @@ let UserInfoEngine = class UserInfoEngine extends BaseEngine {
536
544
  // ========================================================================
537
545
  /**
538
546
  * Check the user's access status for an application.
547
+ * First checks role-based authorization (ApplicationRole records), then installation status.
539
548
  * @param applicationId - The application ID to check
540
549
  * @returns The user's access status for this application
541
550
  */
542
551
  CheckUserApplicationAccess(applicationId) {
552
+ // Step 1: Check role-based authorization first
553
+ if (!this.UserHasApplicationAccess(applicationId)) {
554
+ return 'not_authorized';
555
+ }
556
+ // Step 2: Then check installation status (existing logic)
543
557
  const userApp = this.GetUserApplicationByAppId(applicationId);
544
558
  if (!userApp) {
545
559
  return 'not_installed';
546
560
  }
547
561
  return userApp.IsActive ? 'installed_active' : 'installed_inactive';
548
562
  }
563
+ /**
564
+ * Checks if the current user's roles grant access to the application.
565
+ * If no ApplicationRole records exist for the app, access is open (backwards compatible).
566
+ * If records exist, user must have at least one role with CanAccess=1.
567
+ */
568
+ UserHasApplicationAccess(applicationId) {
569
+ const appRoles = this._applicationRoles.filter(ar => UUIDsEqual(ar.ApplicationID, applicationId));
570
+ // No role records = open access (backwards compatible)
571
+ if (appRoles.length === 0)
572
+ return true;
573
+ // Check if any of the user's roles have CanAccess=1
574
+ const md = new Metadata();
575
+ const user = md.CurrentUser;
576
+ if (!user || !user.UserRoles)
577
+ return false;
578
+ return user.UserRoles.some(ur => appRoles.some(ar => UUIDsEqual(ar.RoleID, ur.RoleID) && ar.CanAccess));
579
+ }
580
+ /**
581
+ * Checks if the current user can administer a specific application.
582
+ * Requires an explicit ApplicationRole record with CanAdmin=1.
583
+ */
584
+ UserCanAdminApplication(applicationId) {
585
+ const appRoles = this._applicationRoles.filter(ar => UUIDsEqual(ar.ApplicationID, applicationId));
586
+ if (appRoles.length === 0)
587
+ return false; // No admin without explicit grant
588
+ const md = new Metadata();
589
+ const user = md.CurrentUser;
590
+ if (!user || !user.UserRoles)
591
+ return false;
592
+ return user.UserRoles.some(ur => appRoles.some(ar => UUIDsEqual(ar.RoleID, ur.RoleID) && ar.CanAdmin));
593
+ }
549
594
  /**
550
595
  * Check if an application is inactive in the system metadata.
551
596
  * @param applicationId - The application ID to check