import type { ChargingStation } from '../../../ChargingStation.js'
-import type { OCPP16AuthAdapter } from '../adapters/OCPP16AuthAdapter.js'
-import type { OCPP20AuthAdapter } from '../adapters/OCPP20AuthAdapter.js'
import type {
AuthCache,
AuthStrategy,
LocalAuthListManager,
+ OCPPAuthAdapter,
} from '../interfaces/OCPPAuthService.js'
import type { AuthConfiguration } from '../types/AuthTypes.js'
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class AuthComponentFactory {
/**
- * Create OCPP adapters based on charging station version
+ * Create OCPP adapter based on charging station version
* @param chargingStation - Charging station instance used to determine OCPP version
- * @returns Object containing version-specific adapter (OCPP 1.6 or 2.0.x)
+ * @returns Single version-specific adapter (OCPP 1.6 or 2.0.x)
* @throws {Error} When OCPP version is not found or unsupported
*/
- static async createAdapters (chargingStation: ChargingStation): Promise<{
- ocpp16Adapter?: OCPP16AuthAdapter
- ocpp20Adapter?: OCPP20AuthAdapter
- }> {
+ static async createAdapter (chargingStation: ChargingStation): Promise<OCPPAuthAdapter> {
const ocppVersion = chargingStation.stationInfo?.ocppVersion
if (!ocppVersion) {
case OCPPVersion.VERSION_16: {
// Use static import - circular dependency is acceptable here
const { OCPP16AuthAdapter } = await import('../adapters/OCPP16AuthAdapter.js')
- return { ocpp16Adapter: new OCPP16AuthAdapter(chargingStation) }
+ return new OCPP16AuthAdapter(chargingStation)
}
case OCPPVersion.VERSION_20:
case OCPPVersion.VERSION_201: {
// Use static import - circular dependency is acceptable here
const { OCPP20AuthAdapter } = await import('../adapters/OCPP20AuthAdapter.js')
- return { ocpp20Adapter: new OCPP20AuthAdapter(chargingStation) }
+ return new OCPP20AuthAdapter(chargingStation)
}
default:
throw new OCPPError(
/**
* Create certificate authentication strategy
* @param chargingStation - Charging station instance for certificate validation
- * @param adapters - Container holding OCPP version-specific adapters
- * @param adapters.ocpp16Adapter - Optional OCPP 1.6 protocol adapter
- * @param adapters.ocpp20Adapter - Optional OCPP 2.0.x protocol adapter
+ * @param adapter - OCPP version-specific adapter
* @param config - Authentication configuration with certificate settings
* @returns Initialized certificate-based authentication strategy
*/
static async createCertificateStrategy (
chargingStation: ChargingStation,
- adapters: { ocpp16Adapter?: OCPP16AuthAdapter; ocpp20Adapter?: OCPP20AuthAdapter },
+ adapter: OCPPAuthAdapter,
config: AuthConfiguration
): Promise<AuthStrategy> {
// Use static import - circular dependency is acceptable here
const { CertificateAuthStrategy } = await import('../strategies/CertificateAuthStrategy.js')
- const adapterMap = new Map<OCPPVersion, OCPP16AuthAdapter | OCPP20AuthAdapter>()
- if (adapters.ocpp16Adapter) {
- adapterMap.set(OCPPVersion.VERSION_16, adapters.ocpp16Adapter)
- }
- if (adapters.ocpp20Adapter) {
- adapterMap.set(OCPPVersion.VERSION_20, adapters.ocpp20Adapter)
- adapterMap.set(OCPPVersion.VERSION_201, adapters.ocpp20Adapter)
- }
- const strategy = new CertificateAuthStrategy(chargingStation, adapterMap)
+ const strategy = new CertificateAuthStrategy(chargingStation, adapter)
strategy.initialize(config)
return strategy
}
/**
* Create remote authentication strategy
- * @param adapters - Container holding OCPP version-specific adapters
- * @param adapters.ocpp16Adapter - Optional OCPP 1.6 protocol adapter
- * @param adapters.ocpp20Adapter - Optional OCPP 2.0.x protocol adapter
+ * @param adapter - OCPP version-specific adapter
* @param cache - Authorization cache for storing remote auth results
* @param config - Authentication configuration controlling remote auth behavior
* @param localAuthListManager - Optional local auth list manager for R17 cache exclusion
* @returns Remote strategy instance or undefined if remote auth disabled
*/
static async createRemoteStrategy (
- adapters: { ocpp16Adapter?: OCPP16AuthAdapter; ocpp20Adapter?: OCPP20AuthAdapter },
+ adapter: OCPPAuthAdapter,
cache: AuthCache | undefined,
config: AuthConfiguration,
localAuthListManager?: LocalAuthListManager
// Use static import - circular dependency is acceptable here
const { RemoteAuthStrategy } = await import('../strategies/RemoteAuthStrategy.js')
- const adapterMap = new Map<OCPPVersion, OCPP16AuthAdapter | OCPP20AuthAdapter>()
- if (adapters.ocpp16Adapter) {
- adapterMap.set(OCPPVersion.VERSION_16, adapters.ocpp16Adapter)
- }
- if (adapters.ocpp20Adapter) {
- adapterMap.set(OCPPVersion.VERSION_20, adapters.ocpp20Adapter)
- adapterMap.set(OCPPVersion.VERSION_201, adapters.ocpp20Adapter)
- }
- const strategy = new RemoteAuthStrategy(adapterMap, cache, localAuthListManager)
+ const strategy = new RemoteAuthStrategy(adapter, cache, localAuthListManager)
strategy.initialize(config)
return strategy
}
/**
* Create all authentication strategies based on configuration
* @param chargingStation - Charging station instance for strategy initialization
- * @param adapters - Container holding OCPP version-specific adapters
- * @param adapters.ocpp16Adapter - Optional OCPP 1.6 protocol adapter
- * @param adapters.ocpp20Adapter - Optional OCPP 2.0.x protocol adapter
+ * @param adapter - OCPP version-specific adapter
* @param manager - Local auth list manager for local strategy
* @param cache - Authorization cache shared across strategies
* @param config - Authentication configuration controlling strategy creation
*/
static async createStrategies (
chargingStation: ChargingStation,
- adapters: { ocpp16Adapter?: OCPP16AuthAdapter; ocpp20Adapter?: OCPP20AuthAdapter },
+ adapter: OCPPAuthAdapter,
manager: LocalAuthListManager | undefined,
cache: AuthCache | undefined,
config: AuthConfiguration
}
// Add remote strategy if enabled
- const remoteStrategy = await this.createRemoteStrategy(adapters, cache, config, manager)
+ const remoteStrategy = await this.createRemoteStrategy(adapter, cache, config, manager)
if (remoteStrategy) {
strategies.push(remoteStrategy)
}
// Always add certificate strategy
- const certStrategy = await this.createCertificateStrategy(chargingStation, adapters, config)
+ const certStrategy = await this.createCertificateStrategy(chargingStation, adapter, config)
strategies.push(certStrategy)
// Sort by priority
import type { OCPP20IdTokenInfoType } from '../../../../types/index.js'
-import type { OCPP16AuthAdapter } from '../adapters/OCPP16AuthAdapter.js'
-import type { OCPP20AuthAdapter } from '../adapters/OCPP20AuthAdapter.js'
+import type { OCPPAuthAdapter } from '../interfaces/OCPPAuthService.js'
import type { LocalAuthStrategy } from '../strategies/LocalAuthStrategy.js'
import { OCPPError } from '../../../../exception/index.js'
const moduleName = 'OCPPAuthServiceImpl'
export class OCPPAuthServiceImpl implements OCPPAuthService {
- private readonly adapters: Map<OCPPVersion, OCPP16AuthAdapter | OCPP20AuthAdapter>
+ private adapter?: OCPPAuthAdapter
private readonly chargingStation: ChargingStation
private config: AuthConfiguration
private readonly metrics: {
constructor (chargingStation: ChargingStation) {
this.chargingStation = chargingStation
this.strategies = new Map()
- this.adapters = new Map()
this.strategyPriority = ['local', 'remote', 'certificate']
// Initialize metrics tracking
// Initialize default configuration
this.config = this.createDefaultConfiguration()
- // Note: Adapters and strategies will be initialized async via initialize()
+ // Note: Adapter and strategies will be initialized async via initialize()
}
/**
* Must be called after construction
*/
public async initialize (): Promise<void> {
- await this.initializeAdapters()
+ await this.initializeAdapter()
await this.initializeStrategies()
}
return false
}
- // Check if any adapter reports remote availability
- for (const adapter of this.adapters.values()) {
+ // Check if adapter reports remote availability
+ if (this.adapter) {
try {
- if (adapter.isRemoteAvailable()) {
+ if (this.adapter.isRemoteAvailable()) {
return true
}
} catch {
- // Continue checking other adapters
+ // Adapter unavailable
}
}
}
/**
- * Initialize OCPP adapters using AuthComponentFactory
+ * Initialize OCPP adapter using AuthComponentFactory
*/
- private async initializeAdapters (): Promise<void> {
- const adapters = await AuthComponentFactory.createAdapters(this.chargingStation)
-
- if (adapters.ocpp16Adapter) {
- this.adapters.set(OCPPVersion.VERSION_16, adapters.ocpp16Adapter)
- }
-
- if (adapters.ocpp20Adapter) {
- this.adapters.set(OCPPVersion.VERSION_20, adapters.ocpp20Adapter)
- this.adapters.set(OCPPVersion.VERSION_201, adapters.ocpp20Adapter)
- }
+ private async initializeAdapter (): Promise<void> {
+ this.adapter = await AuthComponentFactory.createAdapter(this.chargingStation)
}
/**
private async initializeStrategies (): Promise<void> {
const ocppVersion = this.chargingStation.stationInfo?.ocppVersion
- // Get adapters for strategy creation with proper typing
- const ocpp16Adapter = this.adapters.get(OCPPVersion.VERSION_16) as OCPP16AuthAdapter | undefined
- const ocpp20Adapter = this.adapters.get(OCPPVersion.VERSION_20) as OCPP20AuthAdapter | undefined
+ if (this.adapter == null) {
+ throw new OCPPError(ErrorType.INTERNAL_ERROR, 'Adapter must be initialized before strategies')
+ }
// Create auth cache for strategy injection
const authCache = AuthComponentFactory.createAuthCache(this.config)
// Create strategies using factory
const strategies = await AuthComponentFactory.createStrategies(
this.chargingStation,
- { ocpp16Adapter, ocpp20Adapter },
+ this.adapter,
undefined, // manager - delegated to OCPPAuthServiceImpl
authCache,
this.config
public readonly name = 'CertificateAuthStrategy'
public readonly priority = 3
- private readonly adapters: Map<OCPPVersion, OCPPAuthAdapter>
+ private readonly adapter: OCPPAuthAdapter
private readonly chargingStation: ChargingStation
private isInitialized = false
private stats = {
totalRequests: 0,
}
- constructor (chargingStation: ChargingStation, adapters: Map<OCPPVersion, OCPPAuthAdapter>) {
+ constructor (chargingStation: ChargingStation, adapter: OCPPAuthAdapter) {
this.chargingStation = chargingStation
- this.adapters = adapters
+ this.adapter = adapter
}
/**
)
}
- // Get the appropriate adapter
- const adapter = this.adapters.get(request.identifier.ocppVersion)
- if (!adapter) {
- return this.createFailureResult(
- AuthorizationStatus.INVALID,
- `No adapter available for OCPP ${request.identifier.ocppVersion}`,
- request.identifier,
- startTime
- )
- }
+ const adapter = this.adapter
// For OCPP 2.0, we can use certificate-based validation
if (request.identifier.ocppVersion === OCPPVersion.VERSION_20) {
return false
}
- // Must have an adapter for this OCPP version
- const hasAdapter = this.adapters.has(request.identifier.ocppVersion)
-
// Certificate authentication must be enabled
const certAuthEnabled = config.certificateAuthEnabled
// Must have certificate data in the identifier
const hasCertificateData = this.hasCertificateData(request.identifier)
- return hasAdapter && certAuthEnabled && hasCertificateData && this.isInitialized
+ return certAuthEnabled && hasCertificateData && this.isInitialized
}
cleanup (): void {
-import type { OCPPVersion } from '../../../../types/index.js'
import type {
AuthCache,
AuthStrategy,
public readonly name = 'RemoteAuthStrategy'
public readonly priority = 2 // After local but before certificate
- private adapters = new Map<OCPPVersion, OCPPAuthAdapter>()
+ private adapter?: OCPPAuthAdapter
private authCache?: AuthCache
private isInitialized = false
private localAuthListManager?: LocalAuthListManager
}
constructor (
- adapters?: Map<OCPPVersion, OCPPAuthAdapter>,
+ adapter?: OCPPAuthAdapter,
authCache?: AuthCache,
localAuthListManager?: LocalAuthListManager
) {
- if (adapters) {
- this.adapters = adapters
- }
+ this.adapter = adapter
this.authCache = authCache
this.localAuthListManager = localAuthListManager
}
- /**
- * Add an OCPP adapter for a specific version
- * @param version - OCPP protocol version the adapter handles
- * @param adapter - OCPP authentication adapter instance for remote operations
- */
- public addAdapter (version: OCPPVersion, adapter: OCPPAuthAdapter): void {
- this.adapters.set(version, adapter)
- logger.debug(`${moduleName}: Added OCPP ${version} adapter`)
- }
-
/**
* Authenticate using remote CSMS authorization
* @param request - Authorization request with identifier and context
`${moduleName}: Authenticating ${truncateId(request.identifier.value)} via CSMS for ${request.context}`
)
- // Get appropriate adapter for OCPP version
- const adapter = this.adapters.get(request.identifier.ocppVersion)
+ // Get adapter
+ const adapter = this.adapter
if (!adapter) {
- logger.warn(
- `${moduleName}: No adapter available for OCPP version ${request.identifier.ocppVersion}`
- )
+ logger.warn(`${moduleName}: No adapter available`)
return undefined
}
* Check if this strategy can handle the authentication request
* @param request - Authorization request to evaluate
* @param config - Authentication configuration with remote authorization settings
- * @returns True if an adapter exists for the OCPP version and remote auth is enabled
+ * @returns True if an adapter is available and remote auth is enabled
*/
public canHandle (request: AuthRequest, config: AuthConfiguration): boolean {
- // Can handle if we have an adapter for the identifier's OCPP version
- const hasAdapter = this.adapters.has(request.identifier.ocppVersion)
+ // Can handle if we have an adapter
+ const hasAdapter = this.adapter != null
// Remote authorization must be enabled via configuration
const remoteEnabled = config.remoteAuthorization !== false
logger.info(`${moduleName}: Cleanup completed`)
}
+ /**
+ * Clear the OCPP adapter
+ */
+ public clearAdapter (): void {
+ this.adapter = undefined
+ logger.debug(`${moduleName}: Cleared OCPP adapter`)
+ }
+
/**
* Get strategy statistics
* @returns Strategy statistics including success rates, response times, and error counts
*/
public async getStats (): Promise<Record<string, unknown>> {
const cacheStats = this.authCache ? this.authCache.getStats() : null
- const adapterStats = new Map<string, unknown>()
- // Collect adapter availability status
- for (const [version, adapter] of this.adapters) {
+ let adapterAvailable = false
+ if (this.adapter) {
try {
- const isAvailable = await adapter.isRemoteAvailable()
- adapterStats.set(`ocpp${version}Available`, isAvailable)
- } catch (error) {
- adapterStats.set(`ocpp${version}Available`, false)
+ adapterAvailable = await this.adapter.isRemoteAvailable()
+ } catch {
+ adapterAvailable = false
}
}
return {
...this.stats,
- adapterCount: this.adapters.size,
- adapterStats: Object.fromEntries(adapterStats),
+ adapterAvailable,
cacheStats,
+ hasAdapter: this.adapter != null,
hasAuthCache: !!this.authCache,
isInitialized: this.isInitialized,
networkErrorRate:
}
/**
- * Initialize strategy with configuration and adapters
+ * Initialize strategy with configuration and adapter
* @param config - Authentication configuration for adapter validation
*/
public initialize (config: AuthConfiguration): void {
try {
logger.info(`${moduleName}: Initializing...`)
- // Validate that we have at least one adapter
- if (this.adapters.size === 0) {
- logger.warn(`${moduleName}: No OCPP adapters provided`)
+ // Validate that we have an adapter
+ if (this.adapter == null) {
+ logger.warn(`${moduleName}: No OCPP adapter provided`)
}
const stationVersion = config.ocppVersion ?? 'unknown'
- // Validate adapter configurations (deduplicate by instance to avoid
- // validating the same adapter twice for VERSION_20 and VERSION_201)
- const validatedAdapters = new Set<OCPPAuthAdapter>()
- for (const [, adapter] of this.adapters) {
- if (validatedAdapters.has(adapter)) {
- continue
- }
- validatedAdapters.add(adapter)
+ // Validate adapter configuration
+ if (this.adapter) {
try {
- const isValid = adapter.validateConfiguration(config)
+ const isValid = this.adapter.validateConfiguration(config)
if (!isValid) {
logger.warn(`${moduleName}: Invalid configuration for OCPP ${stationVersion}`)
} else {
}
/**
- * Remove an OCPP adapter
- * @param version - OCPP protocol version of the adapter to remove
- * @returns True if the adapter was found and removed
+ * Set the OCPP adapter
+ * @param adapter - OCPP authentication adapter instance for remote operations
*/
- public removeAdapter (version: OCPPVersion): boolean {
- const removed = this.adapters.delete(version)
- if (removed) {
- logger.debug(`${moduleName}: Removed OCPP ${version} adapter`)
- }
- return removed
+ public setAdapter (adapter: OCPPAuthAdapter): void {
+ this.adapter = adapter
+ logger.debug(`${moduleName}: Set OCPP adapter`)
}
/**
/**
* Test connectivity to remote authorization service
- * @returns True if at least one OCPP adapter can reach its remote service
+ * @returns True if the OCPP adapter can reach its remote service
*/
public async testConnectivity (): Promise<boolean> {
- if (!this.isInitialized || this.adapters.size === 0) {
+ if (!this.isInitialized || this.adapter == null) {
return false
}
- // Test connectivity for all adapters
- const connectivityTests = Array.from(this.adapters.values()).map(async adapter => {
- try {
- return await adapter.isRemoteAvailable()
- } catch (error) {
- return false
- }
- })
-
- const results = await Promise.allSettled(connectivityTests)
-
- // Return true if at least one adapter is available
- return results.some(result => result.status === 'fulfilled' && result.value)
+ try {
+ return await this.adapter.isRemoteAvailable()
+ } catch {
+ return false
+ }
}
/**
standardCleanup()
})
- await describe('createAdapters', async () => {
+ await describe('createAdapter', async () => {
await it('should create OCPP 1.6 adapter', async () => {
const { station: chargingStation } = createMockChargingStation({
stationInfo: { ocppVersion: OCPPVersion.VERSION_16 },
})
- const result = await AuthComponentFactory.createAdapters(chargingStation)
+ const adapter = await AuthComponentFactory.createAdapter(chargingStation)
- assert.notStrictEqual(result.ocpp16Adapter, undefined)
- assert.strictEqual(result.ocpp20Adapter, undefined)
+ assert.notStrictEqual(adapter, undefined)
+ assert.strictEqual(adapter.ocppVersion, OCPPVersion.VERSION_16)
})
await it('should create OCPP 2.0 adapter', async () => {
const { station: chargingStation } = createMockChargingStation({
stationInfo: { ocppVersion: OCPPVersion.VERSION_20 },
})
- const result = await AuthComponentFactory.createAdapters(chargingStation)
+ const adapter = await AuthComponentFactory.createAdapter(chargingStation)
- assert.strictEqual(result.ocpp16Adapter, undefined)
- assert.notStrictEqual(result.ocpp20Adapter, undefined)
+ assert.notStrictEqual(adapter, undefined)
+ assert.strictEqual(adapter.ocppVersion, OCPPVersion.VERSION_20)
})
await it('should create OCPP 2.0.1 adapter', async () => {
const { station: chargingStation } = createMockChargingStation({
stationInfo: { ocppVersion: OCPPVersion.VERSION_201 },
})
- const result = await AuthComponentFactory.createAdapters(chargingStation)
+ const adapter = await AuthComponentFactory.createAdapter(chargingStation)
- assert.strictEqual(result.ocpp16Adapter, undefined)
- assert.notStrictEqual(result.ocpp20Adapter, undefined)
+ assert.notStrictEqual(adapter, undefined)
+ assert.strictEqual(adapter.ocppVersion, OCPPVersion.VERSION_20)
})
await it('should throw error for unsupported version', async () => {
stationInfo: { ocppVersion: 'VERSION_15' as OCPPVersion },
})
- await assert.rejects(AuthComponentFactory.createAdapters(chargingStation), {
+ await assert.rejects(AuthComponentFactory.createAdapter(chargingStation), {
message: /Unsupported OCPP version/,
})
})
const { station: chargingStation } = createMockChargingStation()
chargingStation.stationInfo = undefined
- await assert.rejects(AuthComponentFactory.createAdapters(chargingStation), {
+ await assert.rejects(AuthComponentFactory.createAdapter(chargingStation), {
message: /OCPP version not found/,
})
})
const { station: chargingStation } = createMockChargingStation({
stationInfo: { ocppVersion: OCPPVersion.VERSION_16 },
})
- const adapters = await AuthComponentFactory.createAdapters(chargingStation)
+ const adapter = await AuthComponentFactory.createAdapter(chargingStation)
const config: AuthConfiguration = {
allowOfflineTxForUnknownId: false,
authorizationCacheEnabled: false,
remoteAuthorization: false,
}
- const result = await AuthComponentFactory.createRemoteStrategy(adapters, undefined, config)
+ const result = await AuthComponentFactory.createRemoteStrategy(adapter, undefined, config)
assert.strictEqual(result, undefined)
})
const { station: chargingStation } = createMockChargingStation({
stationInfo: { ocppVersion: OCPPVersion.VERSION_16 },
})
- const adapters = await AuthComponentFactory.createAdapters(chargingStation)
+ const adapter = await AuthComponentFactory.createAdapter(chargingStation)
const config: AuthConfiguration = {
allowOfflineTxForUnknownId: false,
authorizationCacheEnabled: false,
remoteAuthorization: true,
}
- const result = await AuthComponentFactory.createRemoteStrategy(adapters, undefined, config)
+ const result = await AuthComponentFactory.createRemoteStrategy(adapter, undefined, config)
assert.notStrictEqual(result, undefined)
if (result) {
const { station: chargingStation } = createMockChargingStation({
stationInfo: { ocppVersion: OCPPVersion.VERSION_16 },
})
- const adapters = await AuthComponentFactory.createAdapters(chargingStation)
+ const adapter = await AuthComponentFactory.createAdapter(chargingStation)
const config: AuthConfiguration = {
allowOfflineTxForUnknownId: false,
authorizationCacheEnabled: false,
const result = await AuthComponentFactory.createCertificateStrategy(
chargingStation,
- adapters,
+ adapter,
config
)
const { station: chargingStation } = createMockChargingStation({
stationInfo: { ocppVersion: OCPPVersion.VERSION_16 },
})
- const adapters = await AuthComponentFactory.createAdapters(chargingStation)
+ const adapter = await AuthComponentFactory.createAdapter(chargingStation)
const config: AuthConfiguration = {
allowOfflineTxForUnknownId: false,
authorizationCacheEnabled: false,
const result = await AuthComponentFactory.createStrategies(
chargingStation,
- adapters,
+ adapter,
undefined,
undefined,
config
const { station: chargingStation } = createMockChargingStation({
stationInfo: { ocppVersion: OCPPVersion.VERSION_16 },
})
- const adapters = await AuthComponentFactory.createAdapters(chargingStation)
+ const adapter = await AuthComponentFactory.createAdapter(chargingStation)
const config: AuthConfiguration = {
allowOfflineTxForUnknownId: false,
authorizationCacheEnabled: false,
const result = await AuthComponentFactory.createStrategies(
chargingStation,
- adapters,
+ adapter,
undefined,
undefined,
config
}),
})
- const adapters = new Map<OCPPVersion, OCPPAuthAdapter>()
- adapters.set(OCPPVersion.VERSION_20, mockOCPP20Adapter)
-
- strategy = new CertificateAuthStrategy(mockStation, adapters)
+ strategy = new CertificateAuthStrategy(mockStation, mockOCPP20Adapter)
})
afterEach(() => {
let mockAuthCache: AuthCache
let mockLocalAuthListManager: LocalAuthListManager
let mockOCPP16Adapter: OCPPAuthAdapter
- let mockOCPP20Adapter: OCPPAuthAdapter
beforeEach(() => {
mockAuthCache = createMockAuthCache()
mockLocalAuthListManager = createMockLocalAuthListManager()
mockOCPP16Adapter = createMockOCPPAdapter(OCPPVersion.VERSION_16)
- mockOCPP20Adapter = createMockOCPPAdapter(OCPPVersion.VERSION_20)
- const adapters = new Map<OCPPVersion, OCPPAuthAdapter>()
- adapters.set(OCPPVersion.VERSION_16, mockOCPP16Adapter)
- adapters.set(OCPPVersion.VERSION_20, mockOCPP20Adapter)
-
- strategy = new RemoteAuthStrategy(adapters, mockAuthCache, mockLocalAuthListManager)
+ strategy = new RemoteAuthStrategy(mockOCPP16Adapter, mockAuthCache, mockLocalAuthListManager)
})
afterEach(() => {
})
await describe('initialize', async () => {
- await it('should initialize successfully with adapters', () => {
+ await it('should initialize successfully with adapter', () => {
const config = createTestAuthConfig({ authorizationCacheEnabled: true })
assert.doesNotThrow(() => {
strategy.initialize(config)
})
})
- await it('should validate adapter configurations', () => {
+ await it('should validate adapter configuration', () => {
mockOCPP16Adapter.validateConfiguration = () => true
- mockOCPP20Adapter.validateConfiguration = () => true
const config = createTestAuthConfig()
assert.doesNotThrow(() => {
strategy.initialize(config)
strategy.initialize(config)
})
- await it('should authenticate using OCPP 1.6 adapter', async () => {
+ await it('should authenticate using adapter', async () => {
const config = createTestAuthConfig({ authorizationCacheEnabled: true })
const request = createMockAuthRequest({
identifier: createMockIdentifier(
assert.strictEqual(result.method, AuthenticationMethod.REMOTE_AUTHORIZATION)
})
- await it('should authenticate using OCPP 2.0 adapter', async () => {
- const config = createTestAuthConfig({ authorizationCacheEnabled: true })
- const request = createMockAuthRequest({
- identifier: {
- ocppVersion: OCPPVersion.VERSION_20,
- type: IdentifierType.ID_TAG,
- value: 'REMOTE_TAG_20',
- },
- })
-
- const result = await strategy.authenticate(request, config)
-
- assert.notStrictEqual(result, undefined)
- assert.strictEqual(result?.status, AuthorizationStatus.ACCEPTED)
- assert.strictEqual(result.method, AuthenticationMethod.REMOTE_AUTHORIZATION)
- })
-
await it('should cache successful authorization results', async () => {
let cachedKey: string | undefined
mockAuthCache.set = (key: string) => {
})
await it('should return undefined when no adapter available', async () => {
+ const strategyNoAdapter = new RemoteAuthStrategy(undefined, mockAuthCache)
+ strategyNoAdapter.initialize(createTestAuthConfig())
+
const config = createTestAuthConfig()
const request = createMockAuthRequest({
identifier: {
},
})
- const result = await strategy.authenticate(request, config)
+ const result = await strategyNoAdapter.authenticate(request, config)
assert.strictEqual(result, undefined)
})
})
await describe('adapter management', async () => {
- await it('should add adapter dynamically', () => {
+ await it('should set adapter dynamically', () => {
const newStrategy = new RemoteAuthStrategy()
- newStrategy.addAdapter(OCPPVersion.VERSION_16, mockOCPP16Adapter)
+ newStrategy.setAdapter(mockOCPP16Adapter)
const config = createTestAuthConfig()
const request = createMockAuthRequest({
assert.strictEqual(newStrategy.canHandle(request, config), true)
})
- await it('should remove adapter', () => {
- void strategy.removeAdapter(OCPPVersion.VERSION_16)
+ await it('should clear adapter', () => {
+ strategy.clearAdapter()
const config = createTestAuthConfig()
const request = createMockAuthRequest({
assert.strictEqual(result, false)
})
- await it('should return false when all adapters unavailable', async () => {
+ await it('should return false when adapter unavailable', async () => {
mockOCPP16Adapter.isRemoteAvailable = () => false
- mockOCPP20Adapter.isRemoteAvailable = () => false
strategy.initialize(createTestAuthConfig())
const result = await strategy.testConnectivity()
await describe('getStats', async () => {
await it('should return strategy statistics', async () => {
const stats = await strategy.getStats()
- assert.strictEqual(stats.adapterCount, 2)
+ assert.strictEqual(stats.hasAdapter, true)
assert.strictEqual(stats.failedRemoteAuth, 0)
assert.strictEqual(stats.hasAuthCache, true)
assert.strictEqual(stats.isInitialized, false)
await it('should include adapter statistics', async () => {
strategy.initialize(createTestAuthConfig())
const stats = await strategy.getStats()
- assert.notStrictEqual(stats.adapterStats, undefined)
+ assert.strictEqual(typeof stats.adapterAvailable, 'boolean')
})
})