UNPKG

@memberjunction/ng-shared

Version:

MemberJunction: MJ Explorer Angular Shared Package - utility functions and other reusable elements used across other MJ Angular packages within the MJ Explorer App - do not use outside of MJ Explorer.

198 lines 6.49 kB
import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { Metadata } from '@memberjunction/core'; import { UserInfoEngine } from '@memberjunction/core-entities'; import * as i0 from "@angular/core"; /** * Setting key for developer mode in MJ: User Settings entity */ const DEVELOPER_MODE_SETTING_KEY = 'Explorer.DeveloperMode'; /** * Service to manage Developer Mode functionality across Explorer apps. * * Developer Mode shows additional debugging tools and developer-focused * features in the UI. Only users with Developer, Admin, or System Administrator * roles can enable developer mode. * * Settings are persisted using the MJ: User Settings entity via UserInfoEngine. * * Usage: * ```typescript * constructor(private devMode: DeveloperModeService) {} * * async ngOnInit() { * await this.devMode.Initialize(userEntity); * * // Subscribe to changes * this.devMode.IsEnabled$.subscribe(enabled => { * this.showDevTools = enabled; * }); * } * ``` */ export class DeveloperModeService { _isEnabled$ = new BehaviorSubject(false); _isDeveloper$ = new BehaviorSubject(false); _initialized = false; _currentUser = null; /** * Optional explicit metadata provider. Set via `setProvider()` from a * caller with provider context. Falls back to `Metadata.Provider` when * not set. */ _provider = null; set Provider(value) { this._provider = value; } get Provider() { return this._provider ?? Metadata.Provider; } // Role names that qualify as "developer" static DEVELOPER_ROLES = [ 'Developer', 'Admin', 'System Administrator', 'Integration' ]; /** * Observable for developer mode enabled state. * Emits whenever developer mode is toggled. */ get IsEnabled$() { return this._isEnabled$.asObservable(); } /** * Observable for whether user has developer role. * This determines if they CAN enable developer mode. */ get IsDeveloper$() { return this._isDeveloper$.asObservable(); } /** * Current enabled state (synchronous access) */ get IsEnabled() { return this._isEnabled$.value; } /** * Whether user has developer role (synchronous access) */ get IsDeveloper() { return this._isDeveloper$.value; } /** * Whether the service has been initialized */ get IsInitialized() { return this._initialized; } /** * Initialize service with current user. * Call this after login/authentication completes. */ async Initialize(user) { if (this._initialized) { return; } this._currentUser = user; // Check if user has a developer role (in-memory, no DB round-trip) const hasDeveloperRole = this.checkDeveloperRole(user); this._isDeveloper$.next(hasDeveloperRole); // Load saved preference from User Settings (only if user is a developer) if (hasDeveloperRole) { const savedState = await this.loadSetting(); this._isEnabled$.next(savedState); } else { // Non-developers always have dev mode disabled this._isEnabled$.next(false); } this._initialized = true; } /** * Toggle developer mode on/off. * Only works if user has developer role. * @returns The new state, or false if user cannot enable dev mode */ async Toggle() { if (!this.IsDeveloper) { console.warn('Developer mode not available - user does not have Developer role'); return false; } const newState = !this.IsEnabled; this._isEnabled$.next(newState); await this.saveSetting(newState); return newState; } /** * Enable developer mode (if user has developer role) */ async Enable() { if (this.IsDeveloper) { this._isEnabled$.next(true); await this.saveSetting(true); } } /** * Disable developer mode */ async Disable() { this._isEnabled$.next(false); await this.saveSetting(false); } /** * Reset the service (e.g., on logout) */ Reset() { this._isEnabled$.next(false); this._isDeveloper$.next(false); this._initialized = false; this._currentUser = null; } /** * Load the developer mode setting from User Settings entity */ async loadSetting() { try { const engine = UserInfoEngine.Instance; const settingValue = engine.GetSetting(DEVELOPER_MODE_SETTING_KEY); return settingValue === 'true'; } catch (error) { console.warn('Failed to load developer mode setting:', error); return false; } } /** * Save the developer mode setting to User Settings entity */ async saveSetting(enabled) { try { const engine = UserInfoEngine.Instance; await engine.SetSetting(DEVELOPER_MODE_SETTING_KEY, String(enabled)); } catch (error) { console.warn('Failed to save developer mode setting:', error); } } /** * Check if user has a developer role using the in-memory UserInfo.UserRoles * already loaded by the provider. No DB round-trip required — role names * are denormalized onto each UserRoleInfo as `Role`. */ checkDeveloperRole(user) { const currentUser = this.Provider.CurrentUser; if (!currentUser?.UserRoles?.length) { return false; } const developerRoleSet = new Set(DeveloperModeService.DEVELOPER_ROLES.map(r => r.toLowerCase())); return currentUser.UserRoles.some(ur => ur.Role && developerRoleSet.has(ur.Role.toLowerCase())); } static ɵfac = function DeveloperModeService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DeveloperModeService)(); }; static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: DeveloperModeService, factory: DeveloperModeService.ɵfac, providedIn: 'root' }); } (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DeveloperModeService, [{ type: Injectable, args: [{ providedIn: 'root' }] }], null, null); })(); //# sourceMappingURL=developer-mode.service.js.map