@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.
209 lines • 7.01 kB
JavaScript
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { RunView } 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;
// 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
const hasDeveloperRole = await 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 by querying User Roles entity
*/
async CheckDeveloperRole(user) {
try {
const rv = new RunView();
// Get user's roles via the User Roles junction table
const userRolesResult = await rv.RunView({
EntityName: 'User Roles',
ExtraFilter: `UserID='${user.ID}'`,
ResultType: 'simple',
Fields: ['RoleID']
});
if (!userRolesResult.Success || !userRolesResult.Results?.length) {
return false;
}
const roleIds = userRolesResult.Results.map(ur => ur.RoleID);
// Get the role names
const rolesResult = await rv.RunView({
EntityName: 'Roles',
ExtraFilter: `ID IN (${roleIds.map(id => `'${id}'`).join(',')})`,
ResultType: 'simple',
Fields: ['Name']
});
if (!rolesResult.Success || !rolesResult.Results?.length) {
return false;
}
// Check if any role matches our developer roles (case-insensitive)
const userRoleNames = rolesResult.Results.map(r => r.Name.toLowerCase());
return DeveloperModeService.DEVELOPER_ROLES.some(devRole => userRoleNames.includes(devRole.toLowerCase()));
}
catch (error) {
console.error('Error checking developer role:', error);
return false;
}
}
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