UI Server: factor out authentication code
authorJérôme Benoit <jerome.benoit@sap.com>
Thu, 8 Sep 2022 20:07:15 +0000 (22:07 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Thu, 8 Sep 2022 20:07:15 +0000 (22:07 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
src/charging-station/ChargingStationWorkerBroadcastChannel.ts
src/charging-station/ui-server/AbstractUIServer.ts
src/charging-station/ui-server/UIHttpServer.ts
src/charging-station/ui-server/UIWebSocketServer.ts
src/charging-station/ui-server/ui-services/AbstractUIService.ts
src/charging-station/ui-server/ui-services/UIService001.ts

index a67b9423649b1e0f97003bcf909bc67ff6b6e319..99b16e655923cfca003882e5e4003b0e1e45a327 100644 (file)
@@ -62,6 +62,16 @@ export default class ChargingStationWorkerBroadcastChannel extends WorkerBroadca
         BroadcastChannelProcedureName.CLOSE_CONNECTION,
         () => this.chargingStation.closeWSConnection(),
       ],
+      [
+        BroadcastChannelProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
+        (requestPayload?: BroadcastChannelRequestPayload) =>
+          this.chargingStation.startAutomaticTransactionGenerator(requestPayload.connectorIds),
+      ],
+      [
+        BroadcastChannelProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
+        (requestPayload?: BroadcastChannelRequestPayload) =>
+          this.chargingStation.stopAutomaticTransactionGenerator(requestPayload.connectorIds),
+      ],
       [
         BroadcastChannelProcedureName.START_TRANSACTION,
         async (requestPayload?: BroadcastChannelRequestPayload) =>
@@ -84,16 +94,6 @@ export default class ChargingStationWorkerBroadcastChannel extends WorkerBroadca
             ),
           }),
       ],
-      [
-        BroadcastChannelProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
-        (requestPayload?: BroadcastChannelRequestPayload) =>
-          this.chargingStation.startAutomaticTransactionGenerator(requestPayload.connectorIds),
-      ],
-      [
-        BroadcastChannelProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
-        (requestPayload?: BroadcastChannelRequestPayload) =>
-          this.chargingStation.stopAutomaticTransactionGenerator(requestPayload.connectorIds),
-      ],
       [
         BroadcastChannelProcedureName.AUTHORIZE,
         async (requestPayload?: BroadcastChannelRequestPayload) =>
@@ -190,8 +190,9 @@ export default class ChargingStationWorkerBroadcastChannel extends WorkerBroadca
         errorStack: (error as Error).stack,
         errorDetails: (error as OCPPError).details,
       };
+    } finally {
+      this.sendResponse([uuid, responsePayload]);
     }
-    this.sendResponse([uuid, responsePayload]);
   }
 
   private messageErrorHandler(messageEvent: MessageEvent): void {
index 75f6e8a89c0e2dcd90438e4ba56070dd1165ba47..dad1e0cb9353fae919b08cc18d6006bfd6c262da 100644 (file)
@@ -71,6 +71,16 @@ export abstract class AbstractUIServer {
     );
   }
 
+  protected authenticate(req: IncomingMessage, next: (err?: Error) => void): void {
+    if (this.isBasicAuthEnabled() === true) {
+      if (this.isValidBasicAuth(req) === false) {
+        next(new Error('Unauthorized'));
+      }
+      next();
+    }
+    next();
+  }
+
   public abstract start(): void;
   public abstract sendRequest(request: ProtocolRequest): void;
   public abstract sendResponse(response: ProtocolResponse): void;
index d1615dbbcb893a3bae3454ad5aceac7a2cfb6a8d..6ae03d5d90ce2ace0a903db63ce24f8b101d6842 100644 (file)
@@ -61,13 +61,16 @@ export default class UIHttpServer extends AbstractUIServer {
   }
 
   private requestListener(req: IncomingMessage, res: ServerResponse): void {
-    if (this.authenticate(req) === false) {
-      res.setHeader('Content-Type', 'text/plain');
-      res.setHeader('WWW-Authenticate', 'Basic realm=users');
-      res.writeHead(StatusCodes.UNAUTHORIZED);
-      res.end(`${StatusCodes.UNAUTHORIZED} Unauthorized`);
-      return;
-    }
+    this.authenticate(req, (err) => {
+      if (err) {
+        res.setHeader('Content-Type', 'text/plain');
+        res.setHeader('WWW-Authenticate', 'Basic realm=users');
+        res.writeHead(StatusCodes.UNAUTHORIZED);
+        res.end(`${StatusCodes.UNAUTHORIZED} Unauthorized`);
+        req.destroy();
+        res.destroy();
+      }
+    });
     // Expected request URL pathname: /ui/:version/:procedureName
     const [protocol, version, procedureName] = req.url?.split('/').slice(1) as [
       Protocol,
@@ -116,16 +119,6 @@ export default class UIHttpServer extends AbstractUIServer {
     }
   }
 
-  private authenticate(req: IncomingMessage): boolean {
-    if (this.isBasicAuthEnabled() === true) {
-      if (this.isValidBasicAuth(req) === true) {
-        return true;
-      }
-      return false;
-    }
-    return true;
-  }
-
   private responseStatusToStatusCode(status: ResponseStatus): StatusCodes {
     switch (status) {
       case ResponseStatus.SUCCESS:
index ce773db37e8387e23ed8370c945fc7b015aa628c..c067fb362a8c8b717312bcff35a049135aac2a23 100644 (file)
@@ -127,18 +127,6 @@ export default class UIWebSocketServer extends AbstractUIServer {
     }
   }
 
-  private authenticate(req: IncomingMessage, next: (err?: Error) => void): void {
-    if (this.isBasicAuthEnabled() === true) {
-      if (this.isValidBasicAuth(req) === false) {
-        next(new Error('Unauthorized'));
-      } else {
-        next();
-      }
-    } else {
-      next();
-    }
-  }
-
   private validateRawDataRequest(rawData: RawData): ProtocolRequest | false {
     // logger.debug(
     //   `${this.logPrefix(
index 356e908ca30d5688de229af443028eff56ef4e1d..6d285926e14593b1fb248fa09583b8e6dae5f0c5 100644 (file)
@@ -73,10 +73,11 @@ export default abstract class AbstractUIService {
         errorStack: (error as Error).stack,
         errorDetails: (error as OCPPError).details,
       };
-    }
-    // Send response for payload not forwarded to broadcast channel
-    if (responsePayload !== undefined) {
-      this.sendResponse(messageId ?? 'error', responsePayload);
+    } finally {
+      // Send response for payload not forwarded to broadcast channel
+      if (responsePayload !== undefined) {
+        this.sendResponse(messageId ?? 'error', responsePayload);
+      }
     }
   }
 
index 82d0a9534adab7972dc615359ebc0e9c99c50cd4..28286d3be62c03b702a5488043b5e4984acc4138 100644 (file)
@@ -47,19 +47,19 @@ export default class UIService001 extends AbstractUIService {
       this.handleProtocolRequest.bind(this) as ProtocolRequestHandler
     );
     this.requestHandlers.set(
-      ProcedureName.START_TRANSACTION,
+      ProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
       this.handleProtocolRequest.bind(this) as ProtocolRequestHandler
     );
     this.requestHandlers.set(
-      ProcedureName.STOP_TRANSACTION,
+      ProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
       this.handleProtocolRequest.bind(this) as ProtocolRequestHandler
     );
     this.requestHandlers.set(
-      ProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
+      ProcedureName.START_TRANSACTION,
       this.handleProtocolRequest.bind(this) as ProtocolRequestHandler
     );
     this.requestHandlers.set(
-      ProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
+      ProcedureName.STOP_TRANSACTION,
       this.handleProtocolRequest.bind(this) as ProtocolRequestHandler
     );
     this.requestHandlers.set(