refactor: factor out UI Server helpers into arrow functions
[e-mobility-charging-stations-simulator.git] / src / charging-station / ui-server / UIServerUtils.ts
index 4d621172b94e7875f6c6bfd683ebd3050f68ec42..2aa2e92b0727a11c4796745142ed06e6c00e7371 100644 (file)
@@ -1,57 +1,64 @@
 import type { IncomingMessage } from 'node:http'
 
+import { BaseError } from '../../exception/index.js'
 import { Protocol, ProtocolVersion } from '../../types/index.js'
 import { logPrefix, logger } from '../../utils/index.js'
 
-// eslint-disable-next-line @typescript-eslint/no-extraneous-class
-export class UIServerUtils {
-  private constructor () {
-    // This is intentional
+export const getUsernameAndPasswordFromAuthorizationToken = (
+  authorizationToken: string,
+  next: (err?: Error) => void
+): [string, string] => {
+  if (
+    !/^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/.test(authorizationToken)
+  ) {
+    next(new BaseError('Invalid basic authentication token format'))
   }
+  const authentication = Buffer.from(authorizationToken, 'base64').toString()
+  const authenticationParts = authentication.split(/:/)
+  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+  return [authenticationParts.shift()!, authenticationParts.join(':')]
+}
 
-  public static readonly handleProtocols = (
-    protocols: Set<string>,
-    request: IncomingMessage
-  ): string | false => {
-    let protocol: Protocol | undefined
-    let version: ProtocolVersion | undefined
-    if (protocols.size === 0) {
-      return false
-    }
-    for (const fullProtocol of protocols) {
-      if (UIServerUtils.isProtocolAndVersionSupported(fullProtocol)) {
-        return fullProtocol
-      }
-    }
-    logger.error(
-      `${logPrefix(
-        ' UI WebSocket Server |'
-      )} Unsupported protocol: '${protocol}' or protocol version: '${version}'`
-    )
+export const handleProtocols = (
+  protocols: Set<string>,
+  _request: IncomingMessage
+): string | false => {
+  let protocol: Protocol | undefined
+  let version: ProtocolVersion | undefined
+  if (protocols.size === 0) {
     return false
   }
-
-  public static readonly isProtocolAndVersionSupported = (protocolStr: string): boolean => {
-    const [protocol, version] = UIServerUtils.getProtocolAndVersion(protocolStr)
-    return (
-      Object.values(Protocol).includes(protocol) && Object.values(ProtocolVersion).includes(version)
-    )
+  for (const fullProtocol of protocols) {
+    if (isProtocolAndVersionSupported(fullProtocol)) {
+      return fullProtocol
+    }
   }
+  logger.error(
+    `${logPrefix(
+      ' UI WebSocket Server |'
+    )} Unsupported protocol: '${protocol}' or protocol version: '${version}'`
+  )
+  return false
+}
 
-  public static readonly getProtocolAndVersion = (
-    protocolStr: string
-  ): [Protocol, ProtocolVersion] => {
-    const protocolIndex = protocolStr.indexOf(Protocol.UI)
-    const protocol = protocolStr.substring(
-      protocolIndex,
-      protocolIndex + Protocol.UI.length
-    ) as Protocol
-    const version = protocolStr.substring(protocolIndex + Protocol.UI.length) as ProtocolVersion
-    return [protocol, version]
-  }
+export const isProtocolAndVersionSupported = (protocolStr: string): boolean => {
+  const [protocol, version] = getProtocolAndVersion(protocolStr)
+  return (
+    Object.values(Protocol).includes(protocol) && Object.values(ProtocolVersion).includes(version)
+  )
+}
 
-  public static isLoopback (address: string): boolean {
-    // eslint-disable-next-line no-useless-escape
-    return /^localhost$|^127(?:\.\d+){0,2}\.\d+$|^(?:0*\:)*?:?0*1$/i.test(address)
-  }
+export const getProtocolAndVersion = (protocolStr: string): [Protocol, ProtocolVersion] => {
+  const protocolIndex = protocolStr.indexOf(Protocol.UI)
+  const protocol = protocolStr.substring(
+    protocolIndex,
+    protocolIndex + Protocol.UI.length
+  ) as Protocol
+  const version = protocolStr.substring(protocolIndex + Protocol.UI.length) as ProtocolVersion
+  return [protocol, version]
+}
+
+export const isLoopback = (address: string): boolean => {
+  // eslint-disable-next-line no-useless-escape
+  return /^localhost$|^127(?:\.\d+){0,2}\.\d+$|^(?:0*\:)*?:?0*1$/i.test(address)
 }