build(deps-dev): apply updates
[e-mobility-charging-stations-simulator.git] / src / charging-station / ui-server / AbstractUIServer.ts
CommitLineData
01f4001e 1import { type IncomingMessage, Server, type ServerResponse } from 'node:http';
daa6505e
JB
2
3import type { WebSocket } from 'ws';
fe94fce0 4
4c3c0d59
JB
5import type { AbstractUIService } from './ui-services/AbstractUIService';
6import { UIServiceFactory } from './ui-services/UIServiceFactory';
7b5dbe91 7import { BaseError } from '../../exception';
eb3abc4f
JB
8import {
9 AuthenticationType,
268a74bb 10 type ChargingStationData,
e0b0ee21
JB
11 type ProcedureName,
12 type ProtocolRequest,
13 type ProtocolResponse,
f130b8e6 14 ProtocolVersion,
e0b0ee21
JB
15 type RequestPayload,
16 type ResponsePayload,
268a74bb
JB
17 type UIServerConfiguration,
18} from '../../types';
8114d10e 19
fe94fce0 20export abstract class AbstractUIServer {
32de5a57 21 public readonly chargingStations: Map<string, ChargingStationData>;
976d11ec
JB
22 protected readonly httpServer: Server;
23 protected readonly responseHandlers: Map<string, ServerResponse | WebSocket>;
5e3cb728 24 protected readonly uiServices: Map<ProtocolVersion, AbstractUIService>;
fe94fce0 25
eb3abc4f 26 public constructor(protected readonly uiServerConfiguration: UIServerConfiguration) {
32de5a57 27 this.chargingStations = new Map<string, ChargingStationData>();
daa6505e 28 this.httpServer = new Server();
94dc3080 29 this.responseHandlers = new Map<string, ServerResponse | WebSocket>();
fe94fce0
JB
30 this.uiServices = new Map<ProtocolVersion, AbstractUIService>();
31 }
32
852a4c5f
JB
33 public buildProtocolRequest(
34 id: string,
35 procedureName: ProcedureName,
5edd8ba0 36 requestPayload: RequestPayload,
5e3cb728
JB
37 ): ProtocolRequest {
38 return [id, procedureName, requestPayload];
852a4c5f
JB
39 }
40
5e3cb728
JB
41 public buildProtocolResponse(id: string, responsePayload: ResponsePayload): ProtocolResponse {
42 return [id, responsePayload];
852a4c5f
JB
43 }
44
daa6505e
JB
45 public stop(): void {
46 this.chargingStations.clear();
47 }
48
7c1395ab 49 public async sendInternalRequest(request: ProtocolRequest): Promise<ProtocolResponse> {
f130b8e6
JB
50 const protocolVersion = ProtocolVersion['0.0.1'];
51 this.registerProtocolVersionUIService(protocolVersion);
52 return this.uiServices.get(protocolVersion)?.requestHandler(request);
6bd808fd
JB
53 }
54
e64c6fa9
JB
55 public hasResponseHandler(id: string): boolean {
56 return this.responseHandlers.has(id);
1ca4a038
JB
57 }
58
a307349b
JB
59 protected startHttpServer(): void {
60 if (this.httpServer.listening === false) {
61 this.httpServer.listen(this.uiServerConfiguration.options);
62 }
63 }
64
143498c8
JB
65 protected registerProtocolVersionUIService(version: ProtocolVersion): void {
66 if (this.uiServices.has(version) === false) {
67 this.uiServices.set(version, UIServiceFactory.getUIServiceImplementation(version, this));
68 }
69 }
70
976d11ec
JB
71 protected authenticate(req: IncomingMessage, next: (err?: Error) => void): void {
72 if (this.isBasicAuthEnabled() === true) {
73 if (this.isValidBasicAuth(req) === false) {
7b5dbe91 74 next(new BaseError('Unauthorized'));
976d11ec
JB
75 }
76 next();
77 }
78 next();
79 }
80
81 private isBasicAuthEnabled(): boolean {
eb3abc4f
JB
82 return (
83 this.uiServerConfiguration.authentication?.enabled === true &&
84 this.uiServerConfiguration.authentication?.type === AuthenticationType.BASIC_AUTH
85 );
86 }
87
976d11ec 88 private isValidBasicAuth(req: IncomingMessage): boolean {
eb3abc4f
JB
89 const authorizationHeader = req.headers.authorization ?? '';
90 const authorizationToken = authorizationHeader.split(/\s+/).pop() ?? '';
91 const authentication = Buffer.from(authorizationToken, 'base64').toString();
92 const authenticationParts = authentication.split(/:/);
93 const username = authenticationParts.shift();
94 const password = authenticationParts.join(':');
95 return (
96 this.uiServerConfiguration.authentication?.username === username &&
97 this.uiServerConfiguration.authentication?.password === password
98 );
99 }
100
fe94fce0 101 public abstract start(): void;
5e3cb728
JB
102 public abstract sendRequest(request: ProtocolRequest): void;
103 public abstract sendResponse(response: ProtocolResponse): void;
104 public abstract logPrefix(
105 moduleName?: string,
106 methodName?: string,
5edd8ba0 107 prefixSuffix?: string,
5e3cb728 108 ): string;
fe94fce0 109}