@memberjunction/ng-auth-services 5.14.0 → 5.16.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.
- package/dist/lib/AngularAuthProviderFactory.d.ts +2 -2
- package/dist/lib/AngularAuthProviderFactory.d.ts.map +1 -1
- package/dist/lib/AngularAuthProviderFactory.js +11 -6
- package/dist/lib/AngularAuthProviderFactory.js.map +1 -1
- package/dist/lib/__tests__/auth-services.test.js +145 -9
- package/dist/lib/__tests__/auth-services.test.js.map +1 -1
- package/dist/lib/mjexplorer-auth-base.service.d.ts +29 -3
- package/dist/lib/mjexplorer-auth-base.service.d.ts.map +1 -1
- package/dist/lib/mjexplorer-auth-base.service.js +45 -0
- package/dist/lib/mjexplorer-auth-base.service.js.map +1 -1
- package/dist/lib/providers/mjexplorer-auth0-provider.service.d.ts +1 -1
- package/dist/lib/providers/mjexplorer-auth0-provider.service.d.ts.map +1 -1
- package/dist/lib/providers/mjexplorer-auth0-provider.service.js +8 -2
- package/dist/lib/providers/mjexplorer-auth0-provider.service.js.map +1 -1
- package/dist/lib/providers/mjexplorer-msal-provider.service.d.ts +1 -1
- package/dist/lib/providers/mjexplorer-msal-provider.service.d.ts.map +1 -1
- package/dist/lib/providers/mjexplorer-msal-provider.service.js +1 -1
- package/dist/lib/providers/mjexplorer-msal-provider.service.js.map +1 -1
- package/dist/lib/providers/mjexplorer-okta-provider.service.d.ts +1 -1
- package/dist/lib/providers/mjexplorer-okta-provider.service.d.ts.map +1 -1
- package/dist/lib/providers/mjexplorer-okta-provider.service.js +1 -1
- package/dist/lib/providers/mjexplorer-okta-provider.service.js.map +1 -1
- package/dist/lib/redirect.component.d.ts +3 -2
- package/dist/lib/redirect.component.d.ts.map +1 -1
- package/dist/lib/redirect.component.js +11 -6
- package/dist/lib/redirect.component.js.map +1 -1
- package/package.json +3 -3
|
@@ -7,14 +7,14 @@ import * as i0 from "@angular/core";
|
|
|
7
7
|
*/
|
|
8
8
|
export declare class AngularAuthProviderFactory {
|
|
9
9
|
private injector;
|
|
10
|
-
private static
|
|
10
|
+
private static readonly _globalStoreKey;
|
|
11
11
|
private providers;
|
|
12
12
|
private providerConfigs;
|
|
13
13
|
constructor(injector: Injector);
|
|
14
14
|
/**
|
|
15
15
|
* Get singleton instance
|
|
16
16
|
*/
|
|
17
|
-
static
|
|
17
|
+
static get Instance(): AngularAuthProviderFactory;
|
|
18
18
|
/**
|
|
19
19
|
* Create a provider based on configuration
|
|
20
20
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AngularAuthProviderFactory.d.ts","sourceRoot":"","sources":["../../src/lib/AngularAuthProviderFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGrD,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;;AAElF;;;GAGG;AACH,qBAGa,0BAA0B;IAKzB,OAAO,CAAC,QAAQ;IAJ5B,OAAO,CAAC,MAAM,CAAC,QAAQ,
|
|
1
|
+
{"version":3,"file":"AngularAuthProviderFactory.d.ts","sourceRoot":"","sources":["../../src/lib/AngularAuthProviderFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGrD,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;;AAElF;;;GAGG;AACH,qBAGa,0BAA0B;IAKzB,OAAO,CAAC,QAAQ;IAJ5B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAA8C;IACrF,OAAO,CAAC,SAAS,CAAgD;IACjE,OAAO,CAAC,eAAe,CAA+B;gBAElC,QAAQ,EAAE,QAAQ;IAQtC;;OAEG;IACH,WAAkB,QAAQ,IAAI,0BAA0B,CAMvD;IAED;;OAEG;IACH,cAAc,CAAC,MAAM,EAAE,yBAAyB,GAAG,oBAAoB;IAoCvE;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS;IAI3D;;OAEG;IACH,kBAAkB,IAAI,MAAM,EAAE;IAO9B;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIvC;;OAEG;IACH,cAAc,IAAI,IAAI;IAKtB;;;OAGG;IACH,MAAM,CAAC,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,GAAG,GAAG,EAAE;yCAnG7D,0BAA0B;6CAA1B,0BAA0B;CAoItC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Injectable } from '@angular/core';
|
|
2
|
-
import { MJGlobal } from '@memberjunction/global';
|
|
2
|
+
import { MJGlobal, GetGlobalObjectStore } from '@memberjunction/global';
|
|
3
3
|
import { MJAuthBase } from './mjexplorer-auth-base.service';
|
|
4
4
|
import * as i0 from "@angular/core";
|
|
5
5
|
/**
|
|
@@ -8,21 +8,26 @@ import * as i0 from "@angular/core";
|
|
|
8
8
|
*/
|
|
9
9
|
export class AngularAuthProviderFactory {
|
|
10
10
|
injector;
|
|
11
|
-
static
|
|
11
|
+
static _globalStoreKey = '___SINGLETON__AngularAuthProviderFactory';
|
|
12
12
|
providers = new Map();
|
|
13
13
|
providerConfigs = new Map();
|
|
14
14
|
constructor(injector) {
|
|
15
15
|
this.injector = injector;
|
|
16
|
-
|
|
16
|
+
const g = GetGlobalObjectStore();
|
|
17
|
+
if (g[AngularAuthProviderFactory._globalStoreKey]) {
|
|
18
|
+
return g[AngularAuthProviderFactory._globalStoreKey];
|
|
19
|
+
}
|
|
20
|
+
g[AngularAuthProviderFactory._globalStoreKey] = this;
|
|
17
21
|
}
|
|
18
22
|
/**
|
|
19
23
|
* Get singleton instance
|
|
20
24
|
*/
|
|
21
|
-
static
|
|
22
|
-
|
|
25
|
+
static get Instance() {
|
|
26
|
+
const instance = GetGlobalObjectStore()[AngularAuthProviderFactory._globalStoreKey];
|
|
27
|
+
if (!instance) {
|
|
23
28
|
throw new Error('AngularAuthProviderFactory not initialized. Ensure it is provided in your module.');
|
|
24
29
|
}
|
|
25
|
-
return
|
|
30
|
+
return instance;
|
|
26
31
|
}
|
|
27
32
|
/**
|
|
28
33
|
* Create a provider based on configuration
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AngularAuthProviderFactory.js","sourceRoot":"","sources":["../../src/lib/AngularAuthProviderFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAY,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"AngularAuthProviderFactory.js","sourceRoot":"","sources":["../../src/lib/AngularAuthProviderFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAY,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;;AAG5D;;;GAGG;AAIH,MAAM,OAAO,0BAA0B;IAKjB;IAJZ,MAAM,CAAU,eAAe,GAAG,0CAA0C,CAAC;IAC7E,SAAS,GAAsC,IAAI,GAAG,EAAE,CAAC;IACzD,eAAe,GAAqB,IAAI,GAAG,EAAE,CAAC;IAEtD,YAAoB,QAAkB;QAAlB,aAAQ,GAAR,QAAQ,CAAU;QACpC,MAAM,CAAC,GAAG,oBAAoB,EAAG,CAAC;QAClC,IAAI,CAAC,CAAC,0BAA0B,CAAC,eAAe,CAAC,EAAE,CAAC;YAClD,OAAO,CAAC,CAAC,0BAA0B,CAAC,eAAe,CAA+B,CAAC;QACrF,CAAC;QACD,CAAC,CAAC,0BAA0B,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC;IACvD,CAAC;IAED;;OAEG;IACI,MAAM,KAAK,QAAQ;QACxB,MAAM,QAAQ,GAAG,oBAAoB,EAAG,CAAC,0BAA0B,CAAC,eAAe,CAA+B,CAAC;QACnH,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,mFAAmF,CAAC,CAAC;QACvG,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,MAAiC;QAE9C,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,gBAAgB,EAAE,CAAC;YACrB,OAAO,gBAAgB,CAAC;QAC1B,CAAC;QAED,IAAI,CAAC;YACH,4DAA4D;YAC5D,gDAAgD;YAChD,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,cAAc,CAC5D,UAAU,EACV,MAAM,CAAC,IAAI,EACX,MAAM,CAAE,oDAAoD;aAC7D,CAAC;YAEF,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CAAC,oCAAoC,MAAM,CAAC,IAAI,sBAAsB,IAAI,CAAC,kBAAkB,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC/H,CAAC;YAED,6BAA6B;YAC7B,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;gBACrC,MAAM,IAAI,KAAK,CAAC,4CAA4C,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YAC7E,CAAC;YAED,8BAA8B;YAC9B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YAC1C,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAE9C,OAAO,QAAQ,CAAC;QAClB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,2CAA2C,MAAM,CAAC,IAAI,GAAG,EAAE,KAAK,CAAC,CAAC;YAChF,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,IAAY;QACtB,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,kBAAkB;QAChB,MAAM,aAAa,GAAG,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,2BAA2B,CAAC,UAAU,CAAC,CAAC;QAC7F,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAiB,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC;QAC7F,oFAAoF;QACpF,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,IAAY;QAC3B,OAAO,IAAI,CAAC,kBAAkB,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;IAC/B,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,0BAA0B,CAAC,IAAY,EAAE,WAAgB;QAE9D,MAAM,cAAc,GAAG,IAAI,EAAE,WAAW,EAAE,CAAC;QAE3C,+CAA+C;QAC/C,MAAM,YAAY,GAAG,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,eAAe,CACjE,UAAU,EACV,cAAc,CACf,CAAC;QACF,MAAM,aAAa,GAAG,YAAY,EAAE,QAAe,CAAC;QAEpD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,CAAC,0CAA0C,IAAI,EAAE,CAAC,CAAC;YAC/D,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,qEAAqE;QACrE,IAAI,aAAa,CAAC,sBAAsB,EAAE,CAAC;YACzC,0DAA0D;YAC1D,MAAM,QAAQ,GAAG,aAAa,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC;YACnE,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,yDAAyD;aACpD,IAAI,OAAO,aAAa,CAAC,2BAA2B,KAAK,UAAU,EAAE,CAAC;YACzE,OAAO,CAAC,IAAI,CAAC,YAAY,IAAI,4GAA4G,CAAC,CAAC;YAC3I,OAAO,aAAa,CAAC,2BAA2B,CAAC,WAAW,CAAC,CAAC;QAChE,CAAC;aACI,CAAC;YACJ,yEAAyE;YACzE,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;oHAlIU,0BAA0B;gEAA1B,0BAA0B,WAA1B,0BAA0B,mBAFzB,MAAM;;iFAEP,0BAA0B;cAHtC,UAAU;eAAC;gBACV,UAAU,EAAE,MAAM;aACnB","sourcesContent":["import { Injectable, Injector } from '@angular/core';\nimport { MJGlobal, GetGlobalObjectStore } from '@memberjunction/global';\nimport { MJAuthBase } from './mjexplorer-auth-base.service';\nimport { IAngularAuthProvider, AngularAuthProviderConfig } from './IAuthProvider';\n\n/**\n * Factory for creating Angular authentication providers\n * Uses MJGlobal ClassFactory pattern for extensibility\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class AngularAuthProviderFactory {\n private static readonly _globalStoreKey = '___SINGLETON__AngularAuthProviderFactory';\n private providers: Map<string, IAngularAuthProvider> = new Map();\n private providerConfigs: Map<string, any> = new Map();\n\n constructor(private injector: Injector) {\n const g = GetGlobalObjectStore()!;\n if (g[AngularAuthProviderFactory._globalStoreKey]) {\n return g[AngularAuthProviderFactory._globalStoreKey] as AngularAuthProviderFactory;\n }\n g[AngularAuthProviderFactory._globalStoreKey] = this;\n }\n\n /**\n * Get singleton instance\n */\n public static get Instance(): AngularAuthProviderFactory {\n const instance = GetGlobalObjectStore()![AngularAuthProviderFactory._globalStoreKey] as AngularAuthProviderFactory;\n if (!instance) {\n throw new Error('AngularAuthProviderFactory not initialized. Ensure it is provided in your module.');\n }\n return instance;\n }\n\n /**\n * Create a provider based on configuration\n */\n createProvider(config: AngularAuthProviderConfig): IAngularAuthProvider {\n \n const existingProvider = this.providers.get(config.type);\n if (existingProvider) {\n return existingProvider;\n }\n\n try {\n // Use MJGlobal ClassFactory to create the provider instance\n // Pass config as the first constructor argument\n const provider = MJGlobal.Instance.ClassFactory.CreateInstance<MJAuthBase>(\n MJAuthBase, \n config.type,\n config // Pass config as constructor argument, not injector\n );\n\n if (!provider) {\n throw new Error(`No provider registered for type: ${config.type}. Available types: ${this.getRegisteredTypes().join(', ')}`);\n }\n\n // Validate the configuration\n if (!provider.validateConfig(config)) {\n throw new Error(`Invalid configuration for provider type: ${config.type}`);\n }\n\n // Store the provider instance\n this.providers.set(config.type, provider);\n this.providerConfigs.set(config.type, config);\n\n return provider;\n } catch (error) {\n console.error(`Failed to create auth provider for type ${config.type}:`, error);\n throw error;\n }\n }\n\n /**\n * Get a provider by type\n */\n getProvider(type: string): IAngularAuthProvider | undefined {\n return this.providers.get(type);\n }\n\n /**\n * Get all registered provider types\n */\n getRegisteredTypes(): string[] {\n const registrations = MJGlobal.Instance.ClassFactory.GetRegistrationsByRootClass(MJAuthBase);\n const types = registrations.map(reg => reg.Key).filter((key): key is string => key !== null);\n // Return unique types only, as multiple classes can be registered with the same key\n return [...new Set(types)];\n }\n\n /**\n * Check if a provider type is registered\n */\n isTypeRegistered(type: string): boolean {\n return this.getRegisteredTypes().includes(type);\n }\n\n /**\n * Clear all providers (useful for testing)\n */\n clearProviders(): void {\n this.providers.clear();\n this.providerConfigs.clear();\n }\n\n /**\n * Get provider-specific Angular services that need to be injected\n * This uses the static angularProviderFactory property on each provider class for extensibility\n */\n static getProviderAngularServices(type: string, environment: any): any[] {\n \n const normalizedType = type?.toLowerCase();\n \n // Get the provider class from the ClassFactory\n const registration = MJGlobal.Instance.ClassFactory.GetRegistration(\n MJAuthBase, \n normalizedType\n );\n const providerClass = registration?.SubClass as any;\n \n if (!providerClass) {\n console.warn(`No provider class registered for type: ${type}`);\n return [];\n }\n \n // Check if the provider class has the factory property (new pattern)\n if (providerClass.angularProviderFactory) {\n // Call the factory function to get the required providers\n const services = providerClass.angularProviderFactory(environment);\n return services;\n } \n // Fallback to old method name for backward compatibility\n else if (typeof providerClass.getRequiredAngularProviders === 'function') {\n console.warn(`Provider ${type} uses deprecated getRequiredAngularProviders method. Please update to use angularProviderFactory property.`);\n return providerClass.getRequiredAngularProviders(environment);\n } \n else {\n // Provider doesn't define required Angular services (might not need any)\n return [];\n }\n }\n\n}"]}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* - Auth types
|
|
5
5
|
* - MJAuthBase (via dynamic import)
|
|
6
6
|
*/
|
|
7
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
7
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
8
8
|
// Mock Angular
|
|
9
9
|
vi.mock('@angular/core', () => ({
|
|
10
10
|
Injectable: () => (target) => target,
|
|
@@ -68,7 +68,7 @@ describe('MJAuthBase', () => {
|
|
|
68
68
|
type = 'test';
|
|
69
69
|
async initialize() { }
|
|
70
70
|
async loginInternal() { }
|
|
71
|
-
async
|
|
71
|
+
async logoutInternal() { }
|
|
72
72
|
async handleCallback() { }
|
|
73
73
|
async extractIdTokenInternal() { return 'token'; }
|
|
74
74
|
async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }
|
|
@@ -87,7 +87,7 @@ describe('MJAuthBase', () => {
|
|
|
87
87
|
type = 'test';
|
|
88
88
|
async initialize() { }
|
|
89
89
|
async loginInternal() { }
|
|
90
|
-
async
|
|
90
|
+
async logoutInternal() { }
|
|
91
91
|
async handleCallback() { }
|
|
92
92
|
async extractIdTokenInternal() { return 'token'; }
|
|
93
93
|
async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }
|
|
@@ -107,7 +107,7 @@ describe('MJAuthBase', () => {
|
|
|
107
107
|
type = 'test';
|
|
108
108
|
async initialize() { }
|
|
109
109
|
async loginInternal() { }
|
|
110
|
-
async
|
|
110
|
+
async logoutInternal() { }
|
|
111
111
|
async handleCallback() { }
|
|
112
112
|
async extractIdTokenInternal() { return 'token'; }
|
|
113
113
|
async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }
|
|
@@ -125,7 +125,7 @@ describe('MJAuthBase', () => {
|
|
|
125
125
|
type = 'test';
|
|
126
126
|
async initialize() { }
|
|
127
127
|
async loginInternal() { }
|
|
128
|
-
async
|
|
128
|
+
async logoutInternal() { }
|
|
129
129
|
async handleCallback() { }
|
|
130
130
|
async extractIdTokenInternal() { return 'token'; }
|
|
131
131
|
async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }
|
|
@@ -145,7 +145,7 @@ describe('MJAuthBase', () => {
|
|
|
145
145
|
type = 'test';
|
|
146
146
|
async initialize() { }
|
|
147
147
|
async loginInternal() { }
|
|
148
|
-
async
|
|
148
|
+
async logoutInternal() { }
|
|
149
149
|
async handleCallback() { }
|
|
150
150
|
async extractIdTokenInternal() { return 'token'; }
|
|
151
151
|
async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }
|
|
@@ -165,7 +165,7 @@ describe('MJAuthBase', () => {
|
|
|
165
165
|
type = 'test';
|
|
166
166
|
async initialize() { }
|
|
167
167
|
async loginInternal() { }
|
|
168
|
-
async
|
|
168
|
+
async logoutInternal() { }
|
|
169
169
|
async handleCallback() { }
|
|
170
170
|
async extractIdTokenInternal() { return 'token'; }
|
|
171
171
|
async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }
|
|
@@ -185,7 +185,7 @@ describe('MJAuthBase', () => {
|
|
|
185
185
|
type = 'test';
|
|
186
186
|
async initialize() { }
|
|
187
187
|
async loginInternal() { }
|
|
188
|
-
async
|
|
188
|
+
async logoutInternal() { }
|
|
189
189
|
async handleCallback() { }
|
|
190
190
|
async extractIdTokenInternal() { return 'my-test-token'; }
|
|
191
191
|
async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }
|
|
@@ -204,7 +204,7 @@ describe('MJAuthBase', () => {
|
|
|
204
204
|
type = 'test';
|
|
205
205
|
async initialize() { }
|
|
206
206
|
async loginInternal() { }
|
|
207
|
-
async
|
|
207
|
+
async logoutInternal() { }
|
|
208
208
|
async handleCallback() { }
|
|
209
209
|
async extractIdTokenInternal() { return 'token'; }
|
|
210
210
|
async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }
|
|
@@ -220,6 +220,142 @@ describe('MJAuthBase', () => {
|
|
|
220
220
|
expect(typeof result.subscribe).toBe('function');
|
|
221
221
|
});
|
|
222
222
|
});
|
|
223
|
+
// ======================= logout and cache clearing =======================
|
|
224
|
+
describe('logout and cache clearing', () => {
|
|
225
|
+
let MJAuthBase;
|
|
226
|
+
beforeEach(async () => {
|
|
227
|
+
global.window = { location: { pathname: '/test', search: '' } };
|
|
228
|
+
const mod = await import('../mjexplorer-auth-base.service');
|
|
229
|
+
MJAuthBase = mod.MJAuthBase;
|
|
230
|
+
});
|
|
231
|
+
afterEach(() => {
|
|
232
|
+
vi.unstubAllGlobals();
|
|
233
|
+
});
|
|
234
|
+
/**
|
|
235
|
+
* Build a minimal TestProvider. The logoutSpy tracks logoutInternal calls.
|
|
236
|
+
* Pass preservedKeys to override the default preservedLocalStorageKeys getter.
|
|
237
|
+
*/
|
|
238
|
+
function makeProvider(preservedKeys) {
|
|
239
|
+
const logoutSpy = vi.fn().mockResolvedValue(undefined);
|
|
240
|
+
class TestProvider extends MJAuthBase {
|
|
241
|
+
type = 'test';
|
|
242
|
+
logoutSpy = logoutSpy;
|
|
243
|
+
async initialize() { }
|
|
244
|
+
async loginInternal() { }
|
|
245
|
+
async logoutInternal() { return logoutSpy(); }
|
|
246
|
+
async handleCallback() { }
|
|
247
|
+
async extractIdTokenInternal() { return 'token'; }
|
|
248
|
+
async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }
|
|
249
|
+
async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }
|
|
250
|
+
async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }
|
|
251
|
+
classifyErrorInternal() { return { type: 'UNKNOWN_ERROR', message: 'err' }; }
|
|
252
|
+
async getProfilePictureUrlInternal() { return null; }
|
|
253
|
+
async handleSessionExpiryInternal() { }
|
|
254
|
+
get preservedLocalStorageKeys() {
|
|
255
|
+
return preservedKeys ?? super.preservedLocalStorageKeys;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });
|
|
259
|
+
}
|
|
260
|
+
/** Stub localStorage with a fixed set of key/value pairs, return a spy on removeItem. */
|
|
261
|
+
function stubLocalStorage(items) {
|
|
262
|
+
const keys = Object.keys(items);
|
|
263
|
+
const removeItem = vi.fn();
|
|
264
|
+
vi.stubGlobal('localStorage', {
|
|
265
|
+
length: keys.length,
|
|
266
|
+
key: (i) => keys[i] ?? null,
|
|
267
|
+
removeItem,
|
|
268
|
+
});
|
|
269
|
+
return { removeItem };
|
|
270
|
+
}
|
|
271
|
+
/** Stub indexedDB.deleteDatabase to resolve immediately via onsuccess. */
|
|
272
|
+
function stubIndexedDB() {
|
|
273
|
+
const deleteDatabase = vi.fn(() => {
|
|
274
|
+
const req = {};
|
|
275
|
+
Object.defineProperty(req, 'onsuccess', { configurable: true, set(fn) { fn(); } });
|
|
276
|
+
Object.defineProperty(req, 'onerror', { configurable: true, set() { } });
|
|
277
|
+
Object.defineProperty(req, 'onblocked', { configurable: true, set() { } });
|
|
278
|
+
return req;
|
|
279
|
+
});
|
|
280
|
+
vi.stubGlobal('indexedDB', { deleteDatabase });
|
|
281
|
+
return { deleteDatabase };
|
|
282
|
+
}
|
|
283
|
+
it('should call logoutInternal during logout', async () => {
|
|
284
|
+
stubLocalStorage({});
|
|
285
|
+
stubIndexedDB();
|
|
286
|
+
const provider = makeProvider();
|
|
287
|
+
await provider.logout();
|
|
288
|
+
expect(provider.logoutSpy).toHaveBeenCalledOnce();
|
|
289
|
+
});
|
|
290
|
+
it('should remove non-preserved localStorage keys on logout', async () => {
|
|
291
|
+
const { removeItem } = stubLocalStorage({
|
|
292
|
+
'mj-session-id': 'abc',
|
|
293
|
+
'auth0.token': 'xyz',
|
|
294
|
+
'mj-login-theme': 'dark',
|
|
295
|
+
});
|
|
296
|
+
stubIndexedDB();
|
|
297
|
+
await makeProvider().logout();
|
|
298
|
+
expect(removeItem).toHaveBeenCalledWith('mj-session-id');
|
|
299
|
+
expect(removeItem).toHaveBeenCalledWith('auth0.token');
|
|
300
|
+
expect(removeItem).not.toHaveBeenCalledWith('mj-login-theme');
|
|
301
|
+
});
|
|
302
|
+
it('should preserve mj-login-theme by default even when it is the only key', async () => {
|
|
303
|
+
const { removeItem } = stubLocalStorage({ 'mj-login-theme': 'dark' });
|
|
304
|
+
stubIndexedDB();
|
|
305
|
+
await makeProvider().logout();
|
|
306
|
+
expect(removeItem).not.toHaveBeenCalled();
|
|
307
|
+
});
|
|
308
|
+
it('should delete the MJ_Metadata IndexedDB on logout', async () => {
|
|
309
|
+
stubLocalStorage({});
|
|
310
|
+
const { deleteDatabase } = stubIndexedDB();
|
|
311
|
+
await makeProvider().logout();
|
|
312
|
+
expect(deleteDatabase).toHaveBeenCalledWith('MJ_Metadata');
|
|
313
|
+
});
|
|
314
|
+
it('should clear caches before calling logoutInternal', async () => {
|
|
315
|
+
const callOrder = [];
|
|
316
|
+
const deleteDatabase = vi.fn(() => {
|
|
317
|
+
callOrder.push('clearCaches');
|
|
318
|
+
const req = {};
|
|
319
|
+
Object.defineProperty(req, 'onsuccess', { configurable: true, set(fn) { fn(); } });
|
|
320
|
+
Object.defineProperty(req, 'onerror', { configurable: true, set() { } });
|
|
321
|
+
Object.defineProperty(req, 'onblocked', { configurable: true, set() { } });
|
|
322
|
+
return req;
|
|
323
|
+
});
|
|
324
|
+
vi.stubGlobal('indexedDB', { deleteDatabase });
|
|
325
|
+
stubLocalStorage({});
|
|
326
|
+
const logoutSpy = vi.fn().mockImplementation(async () => {
|
|
327
|
+
callOrder.push('logoutInternal');
|
|
328
|
+
});
|
|
329
|
+
class OrderTestProvider extends MJAuthBase {
|
|
330
|
+
type = 'test';
|
|
331
|
+
async initialize() { }
|
|
332
|
+
async loginInternal() { }
|
|
333
|
+
async logoutInternal() { return logoutSpy(); }
|
|
334
|
+
async handleCallback() { }
|
|
335
|
+
async extractIdTokenInternal() { return 'token'; }
|
|
336
|
+
async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }
|
|
337
|
+
async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }
|
|
338
|
+
async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }
|
|
339
|
+
classifyErrorInternal() { return { type: 'UNKNOWN_ERROR', message: 'err' }; }
|
|
340
|
+
async getProfilePictureUrlInternal() { return null; }
|
|
341
|
+
async handleSessionExpiryInternal() { }
|
|
342
|
+
}
|
|
343
|
+
await new OrderTestProvider({ name: 'test', type: 'test', clientId: 'test-client' }).logout();
|
|
344
|
+
expect(callOrder).toEqual(['clearCaches', 'logoutInternal']);
|
|
345
|
+
});
|
|
346
|
+
it('should respect overridden preservedLocalStorageKeys in a subclass', async () => {
|
|
347
|
+
const { removeItem } = stubLocalStorage({
|
|
348
|
+
'mj-login-theme': 'dark',
|
|
349
|
+
'my-app-setting': 'value',
|
|
350
|
+
'session-data': 'to-remove',
|
|
351
|
+
});
|
|
352
|
+
stubIndexedDB();
|
|
353
|
+
await makeProvider(new Set(['mj-login-theme', 'my-app-setting'])).logout();
|
|
354
|
+
expect(removeItem).toHaveBeenCalledWith('session-data');
|
|
355
|
+
expect(removeItem).not.toHaveBeenCalledWith('mj-login-theme');
|
|
356
|
+
expect(removeItem).not.toHaveBeenCalledWith('my-app-setting');
|
|
357
|
+
});
|
|
358
|
+
});
|
|
223
359
|
// ======================= AngularAuthProviderFactory =======================
|
|
224
360
|
describe('AngularAuthProviderFactory', () => {
|
|
225
361
|
let Factory;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-services.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/auth-services.test.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tests for auth-services package:\n * - AngularAuthProviderFactory\n * - Auth types\n * - MJAuthBase (via dynamic import)\n */\nimport { describe, it, expect, vi, beforeEach } from 'vitest';\nimport { AuthErrorType } from '../auth-types';\n\n// Mock Angular\nvi.mock('@angular/core', () => ({\n Injectable: () => (target: Function) => target,\n Injector: class {},\n}));\n\nvi.mock('@memberjunction/global', () => ({\n MJGlobal: {\n Instance: {\n ClassFactory: {\n CreateInstance: vi.fn(),\n GetRegistrationsByRootClass: vi.fn(() => []),\n GetRegistration: vi.fn(),\n },\n }\n },\n}));\n\nvi.mock('@memberjunction/core', () => ({\n AuthProviderConfig: class {},\n}));\n\nvi.mock('rxjs', async () => {\n const actual = await vi.importActual<typeof import('rxjs')>('rxjs');\n return actual;\n});\n\n// ======================= Auth types =======================\ndescribe('AuthErrorType enum', () => {\n it('should have expected error types', async () => {\n const { AuthErrorType } = await import('../auth-types');\n expect(AuthErrorType.TOKEN_EXPIRED).toBe('TOKEN_EXPIRED');\n expect(AuthErrorType.NO_ACTIVE_SESSION).toBe('NO_ACTIVE_SESSION');\n expect(AuthErrorType.INTERACTION_REQUIRED).toBe('INTERACTION_REQUIRED');\n expect(AuthErrorType.USER_CANCELLED).toBe('USER_CANCELLED');\n expect(AuthErrorType.NETWORK_ERROR).toBe('NETWORK_ERROR');\n expect(AuthErrorType.CONFIGURATION_ERROR).toBe('CONFIGURATION_ERROR');\n expect(AuthErrorType.UNKNOWN_ERROR).toBe('UNKNOWN_ERROR');\n });\n});\n\n// ======================= IAuthProvider interface =======================\ndescribe('IAuthProvider interface', () => {\n it('should export the interface module', async () => {\n const mod = await import('../IAuthProvider');\n expect(mod).toBeDefined();\n });\n});\n\n// ======================= MJAuthBase =======================\ndescribe('MJAuthBase', () => {\n let MJAuthBase: typeof import('../mjexplorer-auth-base.service').MJAuthBase;\n\n beforeEach(async () => {\n // Mock window before importing\n (global as Record<string, unknown>).window = { location: { pathname: '/test', search: '?q=1' } };\n\n const mod = await import('../mjexplorer-auth-base.service');\n MJAuthBase = mod.MJAuthBase;\n });\n\n it('should be importable', () => {\n expect(MJAuthBase).toBeDefined();\n });\n\n it('should capture initial window location in constructor', () => {\n // Create a concrete test subclass inline\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n async logout(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n expect(provider.initialPath).toBe('/test');\n expect(provider.initialSearch).toBe('?q=1');\n });\n\n it('should validate config with clientId', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n async logout(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n expect(provider.validateConfig({ clientId: 'my-client' })).toBe(true);\n expect(provider.validateConfig({})).toBe(false);\n expect(provider.validateConfig({ clientId: '' })).toBe(false);\n });\n\n it('should return clientId as required config', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n async logout(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n expect(provider.getRequiredConfig()).toEqual(['clientId']);\n });\n\n it('should emit false for isAuthenticated initially', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n async logout(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n let value: boolean | undefined;\n provider.isAuthenticated().subscribe(v => value = v);\n expect(value).toBe(false);\n });\n\n it('should emit null for getUserInfo initially', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n async logout(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n let value: unknown = 'not-null';\n provider.getUserInfo().subscribe(v => value = v);\n expect(value).toBeNull();\n });\n\n it('should delegate classifyError to classifyErrorInternal', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n async logout(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'Custom error msg' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n const result = provider.classifyError(new Error('test'));\n expect(result.type).toBe('UNKNOWN_ERROR');\n expect(result.message).toBe('Custom error msg');\n });\n\n it('should return token from getIdToken', async () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n async logout(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'my-test-token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n const token = await provider.getIdToken();\n expect(token).toBe('my-test-token');\n });\n\n it('should return an observable from login', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n async logout(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n const result = provider.login();\n expect(result).toBeDefined();\n expect(typeof result.subscribe).toBe('function');\n });\n});\n\n// ======================= AngularAuthProviderFactory =======================\ndescribe('AngularAuthProviderFactory', () => {\n let Factory: typeof import('../AngularAuthProviderFactory').AngularAuthProviderFactory;\n\n beforeEach(async () => {\n const mod = await import('../AngularAuthProviderFactory');\n Factory = mod.AngularAuthProviderFactory;\n });\n\n it('should create a new factory instance', () => {\n const factory = new Factory({ get: vi.fn() } as never);\n expect(factory).toBeDefined();\n });\n\n it('should return undefined for unregistered provider', () => {\n const factory = new Factory({ get: vi.fn() } as never);\n expect(factory.getProvider('nonexistent')).toBeUndefined();\n });\n\n it('should clear providers', () => {\n const factory = new Factory({ get: vi.fn() } as never);\n factory.clearProviders();\n expect(factory.getProvider('test')).toBeUndefined();\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"auth-services.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/auth-services.test.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tests for auth-services package:\n * - AngularAuthProviderFactory\n * - Auth types\n * - MJAuthBase (via dynamic import)\n */\nimport { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';\nimport { AuthErrorType } from '../auth-types';\n\n// Mock Angular\nvi.mock('@angular/core', () => ({\n Injectable: () => (target: Function) => target,\n Injector: class {},\n}));\n\nvi.mock('@memberjunction/global', () => ({\n MJGlobal: {\n Instance: {\n ClassFactory: {\n CreateInstance: vi.fn(),\n GetRegistrationsByRootClass: vi.fn(() => []),\n GetRegistration: vi.fn(),\n },\n }\n },\n}));\n\nvi.mock('@memberjunction/core', () => ({\n AuthProviderConfig: class {},\n}));\n\nvi.mock('rxjs', async () => {\n const actual = await vi.importActual<typeof import('rxjs')>('rxjs');\n return actual;\n});\n\n// ======================= Auth types =======================\ndescribe('AuthErrorType enum', () => {\n it('should have expected error types', async () => {\n const { AuthErrorType } = await import('../auth-types');\n expect(AuthErrorType.TOKEN_EXPIRED).toBe('TOKEN_EXPIRED');\n expect(AuthErrorType.NO_ACTIVE_SESSION).toBe('NO_ACTIVE_SESSION');\n expect(AuthErrorType.INTERACTION_REQUIRED).toBe('INTERACTION_REQUIRED');\n expect(AuthErrorType.USER_CANCELLED).toBe('USER_CANCELLED');\n expect(AuthErrorType.NETWORK_ERROR).toBe('NETWORK_ERROR');\n expect(AuthErrorType.CONFIGURATION_ERROR).toBe('CONFIGURATION_ERROR');\n expect(AuthErrorType.UNKNOWN_ERROR).toBe('UNKNOWN_ERROR');\n });\n});\n\n// ======================= IAuthProvider interface =======================\ndescribe('IAuthProvider interface', () => {\n it('should export the interface module', async () => {\n const mod = await import('../IAuthProvider');\n expect(mod).toBeDefined();\n });\n});\n\n// ======================= MJAuthBase =======================\ndescribe('MJAuthBase', () => {\n let MJAuthBase: typeof import('../mjexplorer-auth-base.service').MJAuthBase;\n\n beforeEach(async () => {\n // Mock window before importing\n (global as Record<string, unknown>).window = { location: { pathname: '/test', search: '?q=1' } };\n\n const mod = await import('../mjexplorer-auth-base.service');\n MJAuthBase = mod.MJAuthBase;\n });\n\n it('should be importable', () => {\n expect(MJAuthBase).toBeDefined();\n });\n\n it('should capture initial window location in constructor', () => {\n // Create a concrete test subclass inline\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n expect(provider.initialPath).toBe('/test');\n expect(provider.initialSearch).toBe('?q=1');\n });\n\n it('should validate config with clientId', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n expect(provider.validateConfig({ clientId: 'my-client' })).toBe(true);\n expect(provider.validateConfig({})).toBe(false);\n expect(provider.validateConfig({ clientId: '' })).toBe(false);\n });\n\n it('should return clientId as required config', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n expect(provider.getRequiredConfig()).toEqual(['clientId']);\n });\n\n it('should emit false for isAuthenticated initially', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n let value: boolean | undefined;\n provider.isAuthenticated().subscribe(v => value = v);\n expect(value).toBe(false);\n });\n\n it('should emit null for getUserInfo initially', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n let value: unknown = 'not-null';\n provider.getUserInfo().subscribe(v => value = v);\n expect(value).toBeNull();\n });\n\n it('should delegate classifyError to classifyErrorInternal', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'Custom error msg' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n const result = provider.classifyError(new Error('test'));\n expect(result.type).toBe('UNKNOWN_ERROR');\n expect(result.message).toBe('Custom error msg');\n });\n\n it('should return token from getIdToken', async () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'my-test-token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n const token = await provider.getIdToken();\n expect(token).toBe('my-test-token');\n });\n\n it('should return an observable from login', () => {\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> {}\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n\n const provider = new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n const result = provider.login();\n expect(result).toBeDefined();\n expect(typeof result.subscribe).toBe('function');\n });\n});\n\n// ======================= logout and cache clearing =======================\ndescribe('logout and cache clearing', () => {\n let MJAuthBase: typeof import('../mjexplorer-auth-base.service').MJAuthBase;\n\n beforeEach(async () => {\n (global as Record<string, unknown>).window = { location: { pathname: '/test', search: '' } };\n const mod = await import('../mjexplorer-auth-base.service');\n MJAuthBase = mod.MJAuthBase;\n });\n\n afterEach(() => {\n vi.unstubAllGlobals();\n });\n\n /**\n * Build a minimal TestProvider. The logoutSpy tracks logoutInternal calls.\n * Pass preservedKeys to override the default preservedLocalStorageKeys getter.\n */\n function makeProvider(preservedKeys?: Set<string>) {\n const logoutSpy = vi.fn<() => Promise<void>>().mockResolvedValue(undefined);\n class TestProvider extends MJAuthBase {\n readonly type = 'test';\n readonly logoutSpy = logoutSpy;\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> { return logoutSpy(); }\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true as const, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n override get preservedLocalStorageKeys(): Set<string> {\n return preservedKeys ?? super.preservedLocalStorageKeys;\n }\n }\n return new TestProvider({ name: 'test', type: 'test', clientId: 'test-client' });\n }\n\n /** Stub localStorage with a fixed set of key/value pairs, return a spy on removeItem. */\n function stubLocalStorage(items: Record<string, string>) {\n const keys = Object.keys(items);\n const removeItem = vi.fn();\n vi.stubGlobal('localStorage', {\n length: keys.length,\n key: (i: number) => keys[i] ?? null,\n removeItem,\n });\n return { removeItem };\n }\n\n /** Stub indexedDB.deleteDatabase to resolve immediately via onsuccess. */\n function stubIndexedDB() {\n const deleteDatabase = vi.fn(() => {\n const req = {} as Record<string, unknown>;\n Object.defineProperty(req, 'onsuccess', { configurable: true, set(fn: () => void) { fn(); } });\n Object.defineProperty(req, 'onerror', { configurable: true, set() {} });\n Object.defineProperty(req, 'onblocked', { configurable: true, set() {} });\n return req;\n });\n vi.stubGlobal('indexedDB', { deleteDatabase });\n return { deleteDatabase };\n }\n\n it('should call logoutInternal during logout', async () => {\n stubLocalStorage({});\n stubIndexedDB();\n const provider = makeProvider();\n await provider.logout();\n expect(provider.logoutSpy).toHaveBeenCalledOnce();\n });\n\n it('should remove non-preserved localStorage keys on logout', async () => {\n const { removeItem } = stubLocalStorage({\n 'mj-session-id': 'abc',\n 'auth0.token': 'xyz',\n 'mj-login-theme': 'dark',\n });\n stubIndexedDB();\n await makeProvider().logout();\n expect(removeItem).toHaveBeenCalledWith('mj-session-id');\n expect(removeItem).toHaveBeenCalledWith('auth0.token');\n expect(removeItem).not.toHaveBeenCalledWith('mj-login-theme');\n });\n\n it('should preserve mj-login-theme by default even when it is the only key', async () => {\n const { removeItem } = stubLocalStorage({ 'mj-login-theme': 'dark' });\n stubIndexedDB();\n await makeProvider().logout();\n expect(removeItem).not.toHaveBeenCalled();\n });\n\n it('should delete the MJ_Metadata IndexedDB on logout', async () => {\n stubLocalStorage({});\n const { deleteDatabase } = stubIndexedDB();\n await makeProvider().logout();\n expect(deleteDatabase).toHaveBeenCalledWith('MJ_Metadata');\n });\n\n it('should clear caches before calling logoutInternal', async () => {\n const callOrder: string[] = [];\n const deleteDatabase = vi.fn(() => {\n callOrder.push('clearCaches');\n const req = {} as Record<string, unknown>;\n Object.defineProperty(req, 'onsuccess', { configurable: true, set(fn: () => void) { fn(); } });\n Object.defineProperty(req, 'onerror', { configurable: true, set() {} });\n Object.defineProperty(req, 'onblocked', { configurable: true, set() {} });\n return req;\n });\n vi.stubGlobal('indexedDB', { deleteDatabase });\n stubLocalStorage({});\n\n const logoutSpy = vi.fn<() => Promise<void>>().mockImplementation(async () => {\n callOrder.push('logoutInternal');\n });\n class OrderTestProvider extends MJAuthBase {\n readonly type = 'test';\n async initialize(): Promise<void> {}\n protected async loginInternal(): Promise<void> {}\n protected async logoutInternal(): Promise<void> { return logoutSpy(); }\n async handleCallback(): Promise<void> {}\n protected async extractIdTokenInternal() { return 'token'; }\n protected async extractTokenInfoInternal() { return { idToken: 'token', expiresAt: 0 }; }\n protected async extractUserInfoInternal() { return { id: '1', email: 'a@b.c', name: 'Test' }; }\n protected async refreshTokenInternal() { return { success: true as const, token: { idToken: 'token', expiresAt: 0 } }; }\n protected classifyErrorInternal() { return { type: 'UNKNOWN_ERROR' as AuthErrorType, message: 'err' }; }\n protected async getProfilePictureUrlInternal() { return null; }\n protected async handleSessionExpiryInternal() {}\n }\n await new OrderTestProvider({ name: 'test', type: 'test', clientId: 'test-client' }).logout();\n expect(callOrder).toEqual(['clearCaches', 'logoutInternal']);\n });\n\n it('should respect overridden preservedLocalStorageKeys in a subclass', async () => {\n const { removeItem } = stubLocalStorage({\n 'mj-login-theme': 'dark',\n 'my-app-setting': 'value',\n 'session-data': 'to-remove',\n });\n stubIndexedDB();\n await makeProvider(new Set(['mj-login-theme', 'my-app-setting'])).logout();\n expect(removeItem).toHaveBeenCalledWith('session-data');\n expect(removeItem).not.toHaveBeenCalledWith('mj-login-theme');\n expect(removeItem).not.toHaveBeenCalledWith('my-app-setting');\n });\n});\n\n// ======================= AngularAuthProviderFactory =======================\ndescribe('AngularAuthProviderFactory', () => {\n let Factory: typeof import('../AngularAuthProviderFactory').AngularAuthProviderFactory;\n\n beforeEach(async () => {\n const mod = await import('../AngularAuthProviderFactory');\n Factory = mod.AngularAuthProviderFactory;\n });\n\n it('should create a new factory instance', () => {\n const factory = new Factory({ get: vi.fn() } as never);\n expect(factory).toBeDefined();\n });\n\n it('should return undefined for unregistered provider', () => {\n const factory = new Factory({ get: vi.fn() } as never);\n expect(factory.getProvider('nonexistent')).toBeUndefined();\n });\n\n it('should clear providers', () => {\n const factory = new Factory({ get: vi.fn() } as never);\n factory.clearProviders();\n expect(factory.getProvider('test')).toBeUndefined();\n });\n});\n"]}
|
|
@@ -60,11 +60,13 @@ export declare abstract class MJAuthBase implements IAngularAuthProvider {
|
|
|
60
60
|
*/
|
|
61
61
|
protected abstract loginInternal(options?: Record<string, unknown>): Promise<void>;
|
|
62
62
|
/**
|
|
63
|
-
*
|
|
63
|
+
* Provider-specific logout implementation
|
|
64
64
|
*
|
|
65
|
-
* Subclasses implement provider-specific logout flow.
|
|
65
|
+
* Subclasses implement provider-specific logout flow (redirect, SDK logout, etc.).
|
|
66
|
+
* The base class `logout()` calls `clearClientCaches()` before invoking this method,
|
|
67
|
+
* so providers do NOT need to handle cache clearing themselves.
|
|
66
68
|
*/
|
|
67
|
-
abstract
|
|
69
|
+
protected abstract logoutInternal(): Promise<void>;
|
|
68
70
|
/**
|
|
69
71
|
* Handle OAuth callback
|
|
70
72
|
*
|
|
@@ -157,6 +159,30 @@ export declare abstract class MJAuthBase implements IAngularAuthProvider {
|
|
|
157
159
|
* - `this.authBase.login().subscribe()` (Observable)
|
|
158
160
|
*/
|
|
159
161
|
login(options?: Record<string, unknown>): Observable<void>;
|
|
162
|
+
/**
|
|
163
|
+
* Logout — clears all MJ client-side caches then delegates to the provider.
|
|
164
|
+
*
|
|
165
|
+
* Cache clearing happens universally regardless of auth provider so that a
|
|
166
|
+
* subsequent login as a different user never sees the previous user's data.
|
|
167
|
+
* Providers that need to clear additional caches should override
|
|
168
|
+
* `logoutInternal()` and call `super.logoutInternal()` if applicable.
|
|
169
|
+
*/
|
|
170
|
+
logout(): Promise<void>;
|
|
171
|
+
/**
|
|
172
|
+
* localStorage keys that survive a logout (e.g. UI theme preference).
|
|
173
|
+
*
|
|
174
|
+
* Override this getter in a subclass to preserve additional keys specific
|
|
175
|
+
* to your provider or application.
|
|
176
|
+
*/
|
|
177
|
+
protected get preservedLocalStorageKeys(): Set<string>;
|
|
178
|
+
/**
|
|
179
|
+
* Clears MJ client-side caches before logout.
|
|
180
|
+
*
|
|
181
|
+
* Removes all localStorage entries except those returned by
|
|
182
|
+
* `preservedLocalStorageKeys`, and deletes the `MJ_Metadata` IndexedDB
|
|
183
|
+
* database so a subsequent user session starts with a clean slate.
|
|
184
|
+
*/
|
|
185
|
+
protected clearClientCaches(): Promise<void>;
|
|
160
186
|
/**
|
|
161
187
|
* Check if user is authenticated (Observable stream)
|
|
162
188
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mjexplorer-auth-base.service.d.ts","sourceRoot":"","sources":["../../src/lib/mjexplorer-auth-base.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAQ,MAAM,MAAM,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAClF,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,cAAc,CAAC;;AAEtB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,8BACsB,UAAW,YAAW,oBAAoB;IAC9D,SAAS,CAAC,MAAM,EAAE,yBAAyB,CAAC;IAG5C,SAAS,CAAC,gBAAgB,2BAAuC;IACjE,SAAS,CAAC,SAAS,2CAAsD;IACzE,SAAS,CAAC,UAAU,0BAAmC;IAEvD,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,cAAc,CAAuB;IAE7C;;OAEG;IACH,IAAI,WAAW,IAAI,MAAM,GAAG,IAAI,CAE/B;IAED;;OAEG;IACH,IAAI,aAAa,IAAI,MAAM,GAAG,IAAI,CAEjC;IAED;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEnB,MAAM,EAAE,yBAAyB;IAU7C;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAEpC;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAElF
|
|
1
|
+
{"version":3,"file":"mjexplorer-auth-base.service.d.ts","sourceRoot":"","sources":["../../src/lib/mjexplorer-auth-base.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -61,6 +61,51 @@ export class MJAuthBase {
|
|
|
61
61
|
login(options) {
|
|
62
62
|
return from(this.loginInternal(options));
|
|
63
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Logout — clears all MJ client-side caches then delegates to the provider.
|
|
66
|
+
*
|
|
67
|
+
* Cache clearing happens universally regardless of auth provider so that a
|
|
68
|
+
* subsequent login as a different user never sees the previous user's data.
|
|
69
|
+
* Providers that need to clear additional caches should override
|
|
70
|
+
* `logoutInternal()` and call `super.logoutInternal()` if applicable.
|
|
71
|
+
*/
|
|
72
|
+
async logout() {
|
|
73
|
+
await this.clearClientCaches();
|
|
74
|
+
await this.logoutInternal();
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* localStorage keys that survive a logout (e.g. UI theme preference).
|
|
78
|
+
*
|
|
79
|
+
* Override this getter in a subclass to preserve additional keys specific
|
|
80
|
+
* to your provider or application.
|
|
81
|
+
*/
|
|
82
|
+
get preservedLocalStorageKeys() {
|
|
83
|
+
return new Set(['mj-login-theme']);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Clears MJ client-side caches before logout.
|
|
87
|
+
*
|
|
88
|
+
* Removes all localStorage entries except those returned by
|
|
89
|
+
* `preservedLocalStorageKeys`, and deletes the `MJ_Metadata` IndexedDB
|
|
90
|
+
* database so a subsequent user session starts with a clean slate.
|
|
91
|
+
*/
|
|
92
|
+
async clearClientCaches() {
|
|
93
|
+
const preserved = this.preservedLocalStorageKeys;
|
|
94
|
+
const keysToRemove = [];
|
|
95
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
96
|
+
const key = localStorage.key(i);
|
|
97
|
+
if (key && !preserved.has(key)) {
|
|
98
|
+
keysToRemove.push(key);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
keysToRemove.forEach(key => localStorage.removeItem(key));
|
|
102
|
+
await new Promise((resolve) => {
|
|
103
|
+
const req = indexedDB.deleteDatabase('MJ_Metadata');
|
|
104
|
+
req.onsuccess = () => resolve();
|
|
105
|
+
req.onerror = () => resolve();
|
|
106
|
+
req.onblocked = () => resolve();
|
|
107
|
+
});
|
|
108
|
+
}
|
|
64
109
|
/**
|
|
65
110
|
* Check if user is authenticated (Observable stream)
|
|
66
111
|
*
|