From 0e154bd7f6a34ba12ab42bc1bd6e02d7fc70f37d Mon Sep 17 00:00:00 2001 From: LucasBrazi06 Date: Sat, 20 Nov 2021 15:54:47 +0100 Subject: [PATCH 1/3] Json server: close old WS connection when a new dup one is opened --- .../ocpp/json/JsonCentralSystemServer.ts | 24 ++++++++++++++----- src/server/ocpp/json/WSWrapper.ts | 6 +++-- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/server/ocpp/json/JsonCentralSystemServer.ts b/src/server/ocpp/json/JsonCentralSystemServer.ts index 8b7d5a356f..15bf8a90a1 100644 --- a/src/server/ocpp/json/JsonCentralSystemServer.ts +++ b/src/server/ocpp/json/JsonCentralSystemServer.ts @@ -70,6 +70,10 @@ export default class JsonCentralSystemServer extends CentralSystemServer { ping: async (ws: WebSocket, message: ArrayBuffer) => { // Convert const ocppMessage = Utils.convertBufferArrayToString(message); + // Update + if (ws.wsWrapper) { + (ws.wsWrapper as WSWrapper).lastPingDate = new Date(); + } // Get the WS const wsConnection = await this.getWSConnectionFromWebSocket(ws.wsWrapper, false); if (wsConnection) { @@ -79,6 +83,10 @@ export default class JsonCentralSystemServer extends CentralSystemServer { pong: async (ws: WebSocket, message: ArrayBuffer) => { // Convert const ocppMessage = Utils.convertBufferArrayToString(message); + // Update + if (ws.wsWrapper) { + (ws.wsWrapper as WSWrapper).lastPongDate = new Date(); + } // Get the WS const wsConnection = await this.getWSConnectionFromWebSocket(ws.wsWrapper, false); if (wsConnection) { @@ -290,14 +298,18 @@ export default class JsonCentralSystemServer extends CentralSystemServer { // Check WS const result = await this.pingWebSocket(existingWSWrapper); if (result.ok) { - throw new BackendError({ - siteID: wsConnection.getSiteID(), - siteAreaID: wsConnection.getSiteAreaID(), - companyID: wsConnection.getCompanyID(), - chargingStationID: wsConnection.getChargingStationID(), + // Close the old WS and keep the new incoming one + await Logging.logWarning({ + tenantID: existingWSConnection.getTenantID(), + siteID: existingWSConnection.getSiteID(), + siteAreaID: existingWSConnection.getSiteAreaID(), + companyID: existingWSConnection.getCompanyID(), + chargingStationID: existingWSConnection.getChargingStationID(), action, module: MODULE_NAME, method: 'checkWSConnectionAlreadyExists', - message: `WS Connection - Already opened on '${existingWSWrapper.registrationTimestamp.toISOString()}': '${existingWSWrapper.url}'` + message: `WS Connection - Close already opened WS on '${existingWSWrapper.firstConnectionDate.toISOString()}', last pinged on '${existingWSWrapper.lastPingDate ? existingWSWrapper.lastPingDate?.toISOString() : 'N/A'}', last ponged on '${existingWSWrapper.lastPongDate ? existingWSWrapper.lastPongDate?.toISOString() : 'N/A'}' : '${existingWSWrapper.url}'` }); + // Close + await this.closeWebSocket(existingWSConnection.getWS(), WebSocketCloseEventStatusCode.CLOSE_ABNORMAL, 'New incoming connection'); } } } diff --git a/src/server/ocpp/json/WSWrapper.ts b/src/server/ocpp/json/WSWrapper.ts index f31c8c66cc..4946c78b11 100644 --- a/src/server/ocpp/json/WSWrapper.ts +++ b/src/server/ocpp/json/WSWrapper.ts @@ -19,7 +19,9 @@ export default class WSWrapper { public jsonWSConnection: JsonWSConnection; public jsonRestWSConnection: JsonRestWSConnection; public remoteAddress: string; - public registrationTimestamp: Date; + public firstConnectionDate: Date; + public lastPingDate: Date; + public lastPongDate: Date; private ws: WebSocket; @@ -27,7 +29,7 @@ export default class WSWrapper { this.ws = ws; this.url = ws.url; this.remoteAddress = Utils.convertBufferArrayToString(ws.getRemoteAddressAsText()).toString(); - this.registrationTimestamp = new Date(); + this.firstConnectionDate = new Date(); } public send(message: RecognizedString, isBinary?: boolean, compress?: boolean): boolean { From cb59eccc914324c4f2d0f9822d82fa831b90fa57 Mon Sep 17 00:00:00 2001 From: ClaudeROSSI Date: Thu, 21 Apr 2022 22:18:53 +0200 Subject: [PATCH 2/3] billing - hotfix - payment methods - no limit --- .../v1/schemas/billing/billing-payment-methods-get.json | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/assets/server/rest/v1/schemas/billing/billing-payment-methods-get.json b/src/assets/server/rest/v1/schemas/billing/billing-payment-methods-get.json index b294ffbad2..a35bf4cd4a 100644 --- a/src/assets/server/rest/v1/schemas/billing/billing-payment-methods-get.json +++ b/src/assets/server/rest/v1/schemas/billing/billing-payment-methods-get.json @@ -5,16 +5,9 @@ "properties": { "userID": { "$ref": "common#/definitions/id" - }, - "Limit": { - "$ref": "common#/definitions/limit" - }, - "Skip": { - "$ref": "common#/definitions/skip" } }, "required": [ - "userID", - "Limit" + "userID" ] } From 663d02ce3689a777047b0052dff6ba79f47a71a6 Mon Sep 17 00:00:00 2001 From: FABIANO Serge Date: Mon, 9 May 2022 22:28:43 +0200 Subject: [PATCH 3/3] Merge master-qa (#3516) * Billing simple authorization check * Migrate taxes * Invoice migration * Invoice migration - Use auth definition and remove admin - Add params in invoice storage get - Add authorizations functions check and refactoring * Payment methos migration + add flags - Enforce own user authorization filter for payment - Create flag auth depends on the user that is beeing modified - Adapt auth definition for payment method requirement - Add flags for the GUI * Migrate download billing invoice * Billing setting migration * Clean & lint * Including connectorID in site area chart consumption while averaging minute data. * Fixed typo in logs * Bumped version * Bump ajv from 8.8.2 to 8.11.0 Bumps [ajv](https://github.com/ajv-validator/ajv) from 8.8.2 to 8.11.0. - [Release notes](https://github.com/ajv-validator/ajv/releases) - [Commits](https://github.com/ajv-validator/ajv/compare/v8.8.2...v8.11.0) --- updated-dependencies: - dependency-name: ajv dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Refactor - Add appropriate projectfield in action auth - remove 'custom' projectField creation and use auth def - remove user fields for basic user since not authorized * Bump ts-node from 10.4.0 to 10.7.0 Bumps [ts-node](https://github.com/TypeStrong/ts-node) from 10.4.0 to 10.7.0. - [Release notes](https://github.com/TypeStrong/ts-node/releases) - [Commits](https://github.com/TypeStrong/ts-node/compare/v10.4.0...v10.7.0) --- updated-dependencies: - dependency-name: ts-node dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Bump webpack-cli from 4.9.1 to 4.9.2 Bumps [webpack-cli](https://github.com/webpack/webpack-cli) from 4.9.1 to 4.9.2. - [Release notes](https://github.com/webpack/webpack-cli/releases) - [Changelog](https://github.com/webpack/webpack-cli/blob/master/CHANGELOG.md) - [Commits](https://github.com/webpack/webpack-cli/compare/webpack-cli@4.9.1...webpack-cli@4.9.2) --- updated-dependencies: - dependency-name: webpack-cli dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * invoices - minor changes * Bump body-parser from 1.19.1 to 1.20.0 Bumps [body-parser](https://github.com/expressjs/body-parser) from 1.19.1 to 1.20.0. - [Release notes](https://github.com/expressjs/body-parser/releases) - [Changelog](https://github.com/expressjs/body-parser/blob/master/HISTORY.md) - [Commits](https://github.com/expressjs/body-parser/compare/1.19.1...1.20.0) --- updated-dependencies: - dependency-name: body-parser dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Bump webpack from 5.67.0 to 5.72.0 Bumps [webpack](https://github.com/webpack/webpack) from 5.67.0 to 5.72.0. - [Release notes](https://github.com/webpack/webpack/releases) - [Commits](https://github.com/webpack/webpack/compare/v5.67.0...v5.72.0) --- updated-dependencies: - dependency-name: webpack dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Bump chai from 4.3.4 to 4.3.6 Bumps [chai](https://github.com/chaijs/chai) from 4.3.4 to 4.3.6. - [Release notes](https://github.com/chaijs/chai/releases) - [Changelog](https://github.com/chaijs/chai/blob/4.x.x/History.md) - [Commits](https://github.com/chaijs/chai/compare/v4.3.4...v4.3.6) --- updated-dependencies: - dependency-name: chai dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Bump object-sizeof from 1.6.1 to 1.6.3 Bumps [object-sizeof](https://github.com/miktam/sizeof) from 1.6.1 to 1.6.3. - [Release notes](https://github.com/miktam/sizeof/releases) - [Commits](https://github.com/miktam/sizeof/commits) --- updated-dependencies: - dependency-name: object-sizeof dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Bump @types/validator from 13.7.0 to 13.7.2 Bumps [@types/validator](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/validator) from 13.7.0 to 13.7.2. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/validator) --- updated-dependencies: - dependency-name: "@types/validator" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Clean up unecessary auth checks in service classes * amperage limit - wrong value when set to zero * amperage limit * Do not throw auth exception on lists * Avoid uncatched exceptions in import users/badges and in OCPI remote start/stop session * Fixed typos * payment methods - limit is not mandatory * Soft stop external transactions * payment methods - default limit value * Bump moment from 2.29.2 to 2.29.3 Bumps [moment](https://github.com/moment/moment) from 2.29.2 to 2.29.3. - [Release notes](https://github.com/moment/moment/releases) - [Changelog](https://github.com/moment/moment/blob/2.29.3/CHANGELOG.md) - [Commits](https://github.com/moment/moment/compare/2.29.2...2.29.3) --- updated-dependencies: - dependency-name: moment dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Bump convict from 6.2.1 to 6.2.2 Bumps [convict](https://github.com/mozilla/node-convict) from 6.2.1 to 6.2.2. - [Release notes](https://github.com/mozilla/node-convict/releases) - [Changelog](https://github.com/mozilla/node-convict/blob/master/CHANGELOG.md) - [Commits](https://github.com/mozilla/node-convict/compare/v6.2.1...v6.2.2) --- updated-dependencies: - dependency-name: convict dependency-type: direct:development ... Signed-off-by: dependabot[bot] * billing - payment methods - no limit * Double the number of min DB connections * Removed @typescript-eslint/no-misused-promise in routes * Updated sub-modules * Updated sub-modules * Removed Firebase databaseURL property Updated sub-modules * Removed unused property * Updated VSCode recommandations * Added quicktype VSCode recommandation * Fixed typos * Changed OCPI Charging to Preparing when OCPP is Available * Fixed OCPI Remote Start creates RFID Card on the fly * Never calculate the cost of an OCPI transaction * Renamed Loggings routes/types to Logs * Fixed UTs * Fixed typo * pricing - do not price roaming sessions (#3500) * pricing - do not price roaming sessions * pricing - user must be provided Co-authored-by: FABIANO Serge * Validate OCPP Meter Values with Json schema (#3458) * add json meter values request * this.validate meter values in occpvalidation * meterValue, Validator schema for 1.6, had to test for 1.5 * this is how it works for me * final meter value request * split validator * split again ocpp json schema * deleted one step in OCPP16Array schema * split array and object validation for occp15 + default value * added required and $id * No need to have a dedicated OCPP json file * delete the useless "convert to int" and set default * Validation transaction ID === 0 * Put back the check of the Transaction ID > 0 on connector Co-authored-by: BANCHEREAU Caroline Co-authored-by: LucasBrazi06 * Removed circular deps Removed unused indexes * putting back code lost after a merge * Put back userID DB index in tags collection * Fixed auth exception check in Site Area create endpoint * Ensured OCPP Heartbeart body is correct when validated with a Json schema * Avoid NPE in OCPP response * Added UTs for organizations (#3417) * site area tests * add site Area Org script package.json * Sites tests * Assets, Charging stations, Transactions and Consumption should be aligned with organizations entities * Assets, Charging stations and transactions should be aligned with organizations entities * Run AlignEntitiesWithOrganizationIDsTask again. * fix test error * fix test again * Specify all needed fields of a method (golden rule) Co-authored-by: mahdibenromdhane Co-authored-by: ClaudeROSSI Co-authored-by: LucasBrazi06 * Update lastUpdateBy projected field (#3508) * Update projected fields * Align lastchangedby projected field - only return firstName and name * createdby prjected field update (#3510) * Updated sub-modules * Updated sub-modules * Do not update Charging Station max power in master/slave * Put back the fucking name 'vscode-jest-tests' to debug with Jest * Removed useless service utils checks (#3511) * refactor: removed useless checks * refactor: removed useless object structure checks * refactor: reduced useless inner methods checks Co-authored-by: LucasBrazi06 * Optimized load consumptions in MongoDB (#3388) * Mongodb changes * Additional changes * Changing variable names * Variable again!! * Test case changes * fix tests * fix tests Co-authored-by: Claude ROSSI * Updated sub-modules * Updated sub-modules * Removed useless trials in Applying Charging Profiles notification * Fixed typos Co-authored-by: Ramzi Siala <1226644+Ramzay@users.noreply.github.com> Co-authored-by: Rohan Antony Co-authored-by: ClaudeROSSI Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: mahdibenromdhane Co-authored-by: melvyndubois <72790760+melvyndubois@users.noreply.github.com> Co-authored-by: BANCHEREAU Caroline Co-authored-by: mahdibenromdhane <33232018+mahdibenromdhane@users.noreply.github.com> Co-authored-by: Loan Alouache <30394488+Ninjeneer@users.noreply.github.com> --- .vscode/extensions.json | 18 +- .vscode/launch.json | 2 +- package-lock.json | 503 +++++---- package.json | 22 +- postman/EVSE.postman_collection.json | 12 +- src/assets/charging-station-templates | 2 +- src/assets/config-template-http.json | 3 +- src/assets/config-template-https.json | 3 +- src/assets/configs-aws | 2 +- src/assets/configs-ci | 2 +- .../schemas/configuration/configuration.json | 6 +- src/assets/schemas/user/user.json | 9 +- ...te-and-apply-charging-profiles-failed.json | 2 +- ...te-and-apply-charging-profiles-failed.json | 2 +- ...te-and-apply-charging-profiles-failed.json | 2 +- ...te-and-apply-charging-profiles-failed.json | 2 +- ...te-and-apply-charging-profiles-failed.json | 2 +- .../ocpp/schemas/authorize-request.json | 2 +- .../schemas/boot-notification-request.json | 2 +- .../ocpp/schemas/heartbeat-request.json | 2 +- .../ocpp/schemas/meter-values-request.json | 293 ++++++ .../schemas/start-transaction-request.json | 2 +- .../schemas/status-notification-request.json | 2 +- .../schemas/stop-transaction-request-15.json | 2 +- .../schemas/stop-transaction-request-16.json | 4 +- .../server/rest/v1/docs/e-mobility-oas.json | 28 +- .../rest/v1/schemas/asset/asset-create.json | 2 +- .../logging-get.json => log/log-get.json} | 4 +- .../loggings-get.json => log/logs-get.json} | 4 +- src/authorization/AuthorizationsDefinition.ts | 78 +- src/client/ocpi/CpoOCPIClient.ts | 53 +- src/client/ocpi/EmspOCPIClient.ts | 4 +- src/integration/billing/BillingIntegration.ts | 30 +- src/integration/pricing/PricingFacade.ts | 79 ++ .../AlignEntitiesWithOrganizationIDsTask.ts | 2 +- src/notification/NotificationHandler.ts | 10 +- .../RemotePushNotificationTask.ts | 6 +- .../CheckPreparingSessionNotStartedTask.ts | 2 +- ...heckSessionNotStartedAfterAuthorizeTask.ts | 2 +- .../tasks/LoggingDatabaseTableCleanupTask.ts | 6 +- src/server/ocpi/OCPIUtils.ts | 32 +- .../router/cpo/V2.1.1/CPOCdrsRouterV211.ts | 5 +- src/server/ocpi/service/OCPIUtilsService.ts | 6 +- .../service/cpo/v2.1.1/CPOCommandsService.ts | 82 +- .../service/cpo/v2.1.1/CPOTokensService.ts | 2 +- .../ocpp/json/web-socket/JsonWSConnection.ts | 2 +- .../ocpp/json/web-socket/WSConnection.ts | 4 +- src/server/ocpp/services/OCPPService.ts | 35 +- src/server/ocpp/utils/OCPPUtils.ts | 84 +- src/server/ocpp/validation/OCPPValidation.ts | 9 +- src/server/rest/RestServer.ts | 4 +- src/server/rest/RestServerService.ts | 8 +- src/server/rest/v1/router/GlobalRouterV1.ts | 6 +- src/server/rest/v1/router/api/AssetRouter.ts | 41 +- src/server/rest/v1/router/api/CarRouter.ts | 41 +- .../v1/router/api/ChargingStationRouter.ts | 141 ++- .../rest/v1/router/api/CompanyRouter.ts | 21 +- .../rest/v1/router/api/ConnectionRouter.ts | 17 +- src/server/rest/v1/router/api/LogRouter.ts | 39 + .../rest/v1/router/api/LoggingRouter.ts | 40 - .../rest/v1/router/api/NotificationRouter.ts | 9 +- .../rest/v1/router/api/OCPIEndpointRouter.ts | 77 +- .../rest/v1/router/api/OICPEndpointRouter.ts | 41 +- .../rest/v1/router/api/PricingRouter.ts | 25 +- .../v1/router/api/RegistrationTokenRouter.ts | 25 +- .../rest/v1/router/api/SettingRouter.ts | 23 +- .../rest/v1/router/api/SiteAreaRouter.ts | 41 +- src/server/rest/v1/router/api/SiteRouter.ts | 41 +- .../rest/v1/router/api/StatisticsRouter.ts | 49 +- src/server/rest/v1/router/api/TagRouter.ts | 49 +- src/server/rest/v1/router/api/TenantRouter.ts | 21 +- .../rest/v1/router/api/TransactionRouter.ts | 77 +- src/server/rest/v1/router/api/UserRouter.ts | 57 +- src/server/rest/v1/router/auth/AuthRouter.ts | 33 +- src/server/rest/v1/router/util/UtilRouter.ts | 29 +- src/server/rest/v1/service/AssetService.ts | 44 +- src/server/rest/v1/service/AuthService.ts | 2 - .../rest/v1/service/AuthorizationService.ts | 411 +++++--- src/server/rest/v1/service/BillingService.ts | 214 ++-- src/server/rest/v1/service/CarService.ts | 68 +- .../rest/v1/service/ChargingStationService.ts | 12 - src/server/rest/v1/service/CompanyService.ts | 26 +- .../{LoggingService.ts => LogService.ts} | 44 +- .../rest/v1/service/OICPEndpointService.ts | 6 - src/server/rest/v1/service/PricingService.ts | 30 +- .../v1/service/RegistrationTokenService.ts | 27 +- src/server/rest/v1/service/SettingService.ts | 4 - src/server/rest/v1/service/SiteAreaService.ts | 48 +- src/server/rest/v1/service/SiteService.ts | 42 +- src/server/rest/v1/service/TagService.ts | 34 +- .../rest/v1/service/TransactionService.ts | 24 +- src/server/rest/v1/service/UserService.ts | 52 +- src/server/rest/v1/service/UtilsService.ts | 952 ++++-------------- src/server/rest/v1/validator/LogValidator.ts | 31 + .../rest/v1/validator/LoggingValidator.ts | 31 - src/storage/mongodb/BillingStorage.ts | 4 +- src/storage/mongodb/ConsumptionStorage.ts | 132 ++- .../{LoggingStorage.ts => LogStorage.ts} | 16 +- src/storage/mongodb/MongoDBStorage.ts | 8 +- src/storage/mongodb/SettingStorage.ts | 4 +- src/storage/mongodb/SiteAreaStorage.ts | 60 +- src/types/Authorization.ts | 4 + src/types/Billing.ts | 7 +- src/types/DataResult.ts | 9 + src/types/GlobalType.ts | 4 +- src/types/Locking.ts | 2 +- src/types/Server.ts | 13 +- src/types/Setting.ts | 3 +- src/types/configuration/Configuration.ts | 6 +- .../configuration/FirebaseConfiguration.ts | 1 - src/types/configuration/LogConfiguration.ts | 3 + .../configuration/LoggingConfiguration.ts | 3 - ...ttpLoggingRequest.ts => HttpLogRequest.ts} | 0 src/utils/Configuration.ts | 10 +- src/utils/Logging.ts | 26 +- src/utils/NotificationHelper.ts | 22 +- src/utils/Utils.ts | 20 +- src/validator/SchemaValidator.ts | 2 +- test/api/BillingTestHelper.ts | 4 +- test/api/RegistrationTokenTest.ts | 2 +- test/api/SiteAreaOrgTest.ts | 161 ++- test/api/SiteOrgTest.ts | 110 +- test/api/SmartChargingTest.ts | 16 +- test/api/client/LogsApi.ts | 5 +- test/api/client/SiteAreaApi.ts | 2 +- test/api/client/TransactionApi.ts | 3 +- test/api/context/ContextDefinition.ts | 21 +- 127 files changed, 2708 insertions(+), 2506 deletions(-) create mode 100644 src/assets/server/ocpp/schemas/meter-values-request.json rename src/assets/server/rest/v1/schemas/{logging/logging-get.json => log/log-get.json} (75%) rename src/assets/server/rest/v1/schemas/{logging/loggings-get.json => log/logs-get.json} (96%) create mode 100644 src/integration/pricing/PricingFacade.ts create mode 100644 src/server/rest/v1/router/api/LogRouter.ts delete mode 100644 src/server/rest/v1/router/api/LoggingRouter.ts rename src/server/rest/v1/service/{LoggingService.ts => LogService.ts} (73%) create mode 100644 src/server/rest/v1/validator/LogValidator.ts delete mode 100644 src/server/rest/v1/validator/LoggingValidator.ts rename src/storage/mongodb/{LoggingStorage.ts => LogStorage.ts} (93%) create mode 100644 src/types/configuration/LogConfiguration.ts delete mode 100644 src/types/configuration/LoggingConfiguration.ts rename src/types/requests/{HttpLoggingRequest.ts => HttpLogRequest.ts} (100%) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 5366569b3e..4614f3cf7c 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -6,8 +6,20 @@ "codezombiech.gitignore", "dbaeumer.vscode-eslint", "eamodio.gitlens", - "EditorConfig.EditorConfig", + "editorconfig.editorconfig", "ms-azuretools.vscode-docker", - "streetsidesoftware.code-spell-checker" + "streetsidesoftware.code-spell-checker", + "formulahendry.auto-rename-tag", + "naumovs.color-highlight", + "l13rary.l13-diff", + "orta.vscode-jest", + "sonarsource.sonarlint-vscode", + "hbenl.vscode-test-explorer", + "gruntfuggly.todo-tree", + "chakrounanas.turbo-console-log", + "adamhartford.vscode-base64", + "redhat.vscode-yaml", + "christian-kohler.npm-intellisense", + "quicktype.quicktype" ] -} +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 57ee4b517c..db98a97338 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -6,7 +6,7 @@ "configurations": [ { "type": "node", - "name": "Run all Tests", + "name": "vscode-jest-tests", "request": "launch", "program": "${workspaceFolder}/node_modules/.bin/jest", "args": [ diff --git a/package-lock.json b/package-lock.json index e751619958..e557afe227 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "ev-server", - "version": "2.6.5", + "version": "2.6.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ev-server", - "version": "2.6.5", + "version": "2.6.6", "license": "Apache-2.0", "dependencies": { - "ajv": "^8.6.3", + "ajv": "^8.11.0", "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0", "axios": "^0.25.0", @@ -17,7 +17,7 @@ "basic-auth": "^2.0.1", "bcryptjs": "^2.4.3", "bluebird": "^3.7.2", - "body-parser": "^1.19.1", + "body-parser": "^1.20.0", "body-parser-xml": "^2.0.3", "busboy": "^1.4.0", "chalk": "^4.1.2", @@ -43,7 +43,7 @@ "jsonwebtoken": "^8.5.1", "locale": "^0.1.0", "lodash": "^4.17.21", - "moment": "^2.29.2", + "moment": "^2.29.3", "moment-duration-format": "^2.3.2", "moment-timezone": "^0.5.34", "mongo-sanitize": "^1.1.0", @@ -53,7 +53,7 @@ "mustache": "^4.2.0", "nanoid": "^3.2.0", "node-cron": "^3.0.0", - "object-sizeof": "^1.6.1", + "object-sizeof": "^1.6.3", "passport": "^0.5.2", "passport-jwt": "^4.0.0", "password-generator": "^2.3.2", @@ -115,18 +115,18 @@ "@types/tz-lookup": "^6.1.0", "@types/urlencode": "^1.1.2", "@types/uuid": "^8.3.4", - "@types/validator": "^13.7.0", + "@types/validator": "^13.7.2", "@types/ws": "^8.2.2", "@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/parser": "^4.32.0", "autocannon": "^7.6.0", - "chai": "^4.3.4", + "chai": "^4.3.6", "chai-datetime": "^1.8.0", "chai-subset": "^1.6.0", "circular-dependency-plugin": "^5.2.2", "clean-webpack-plugin": "^4.0.0", "clinic": "^10.0.0", - "convict": "^6.2.0", + "convict": "^6.2.2", "copy-webpack-plugin": "^9.0.1", "cross-env": "^7.0.3", "deep-object-diff": "^1.1.0", @@ -146,11 +146,11 @@ "rosie": "^2.1.0", "ts-jest": "^27.1.3", "ts-loader": "^9.2.6", - "ts-node": "^10.3.0", + "ts-node": "^10.7.0", "ts-node-dev": "^1.1.8", "typescript": "^4.5.4", - "webpack": "^5.67.0", - "webpack-cli": "^4.9.1", + "webpack": "^5.72.0", + "webpack-cli": "^4.9.2", "webpack-merge": "^5.8.0", "webpack-node-externals": "^3.0.0", "webpack-shell-plugin-next": "^2.2.2", @@ -3669,9 +3669,9 @@ "dev": true }, "node_modules/@types/eslint": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.28.2.tgz", - "integrity": "sha512-KubbADPkfoU75KgKeKLsFHXnU4ipH7wYg0TRT33NK3N3yiu7jlFAAoygIWBV+KbuHx/G+AvuGX6DllnK35gfJA==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz", + "integrity": "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==", "dev": true, "dependencies": { "@types/estree": "*", @@ -3679,9 +3679,9 @@ } }, "node_modules/@types/eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha512-SCFeogqiptms4Fg29WpOTk5nHIzfpKCemSN63ksBQYKTcXoJEmJagV+DhVmbapZzY4/5YaOV1nZwrsU79fFm1g==", + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", "dev": true, "dependencies": { "@types/eslint": "*", @@ -3689,9 +3689,9 @@ } }, "node_modules/@types/estree": { - "version": "0.0.50", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", - "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", "dev": true }, "node_modules/@types/express": { @@ -4059,9 +4059,9 @@ "dev": true }, "node_modules/@types/validator": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.0.tgz", - "integrity": "sha512-+jBxVvXVuggZOrm04NR8z+5+bgoW4VZyLzUO+hmPPW1mVFL/HaitLAkizfv4yg9TbG8lkfHWVMQ11yDqrVVCzA==", + "version": "13.7.2", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.2.tgz", + "integrity": "sha512-KFcchQ3h0OPQgFirBRPZr5F/sVjxZsOrQHedj3zi8AH3Zv/hOLx2OLR4hxR5HcfoU+33n69ZuOfzthKVdMoTiw==", "dev": true }, "node_modules/@types/webgl-ext": { @@ -4445,9 +4445,9 @@ } }, "node_modules/@webpack-cli/configtest": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.0.tgz", - "integrity": "sha512-ttOkEkoalEHa7RaFYpM0ErK1xc4twg3Am9hfHhL7MVqlHebnkYd2wuI/ZqTDj0cVzZho6PdinY0phFZV3O0Mzg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.1.tgz", + "integrity": "sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg==", "dev": true, "peerDependencies": { "webpack": "4.x.x || 5.x.x", @@ -4455,9 +4455,9 @@ } }, "node_modules/@webpack-cli/info": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.0.tgz", - "integrity": "sha512-F6b+Man0rwE4n0409FyAJHStYA5OIZERxmnUfLVwv0mc0V1wLad3V7jqRlMkgKBeAq07jUvglacNaa6g9lOpuw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.1.tgz", + "integrity": "sha512-PKVGmazEq3oAo46Q63tpMr4HipI3OPfP7LiNOEJg963RMgT0rqheag28NCML0o3GIzA3DmxP1ZIAv9oTX1CUIA==", "dev": true, "dependencies": { "envinfo": "^7.7.3" @@ -4467,9 +4467,9 @@ } }, "node_modules/@webpack-cli/serve": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.0.tgz", - "integrity": "sha512-ZkVeqEmRpBV2GHvjjUZqEai2PpUbuq8Bqd//vEYsp63J8WyexI8ppCqVS3Zs0QADf6aWuPdU+0XsPI647PVlQA==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.1.tgz", + "integrity": "sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw==", "dev": true, "peerDependencies": { "webpack-cli": "4.x.x" @@ -4872,9 +4872,9 @@ } }, "node_modules/ajv": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz", - "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -5765,23 +5765,26 @@ "dev": true }, "node_modules/body-parser": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz", - "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", "dependencies": { - "bytes": "3.1.1", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.6", - "raw-body": "2.4.2", - "type-is": "~1.6.18" + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, "node_modules/body-parser-xml": { @@ -5803,19 +5806,36 @@ "ms": "2.0.0" } }, + "node_modules/body-parser/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, "node_modules/body-parser/node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dependencies": { - "depd": "~1.1.2", + "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", + "statuses": "2.0.1", "toidentifier": "1.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/body-parser/node_modules/ms": { @@ -5823,10 +5843,24 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "node_modules/body-parser/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/body-parser/node_modules/qs": { - "version": "6.9.6", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", - "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==", + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "dependencies": { + "side-channel": "^1.0.4" + }, "engines": { "node": ">=0.6" }, @@ -5839,6 +5873,14 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "node_modules/body-parser/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/body-parser/node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -6330,9 +6372,9 @@ } }, "node_modules/bytes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", - "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "engines": { "node": ">= 0.8" } @@ -6591,15 +6633,16 @@ "dev": true }, "node_modules/chai": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", - "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", + "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", "dev": true, "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", "deep-eql": "^3.0.1", "get-func-name": "^2.0.0", + "loupe": "^2.3.1", "pathval": "^1.1.1", "type-detect": "^4.0.5" }, @@ -7318,9 +7361,9 @@ "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=" }, "node_modules/convict": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/convict/-/convict-6.2.1.tgz", - "integrity": "sha512-Mn4AJiYkR3TAZH1Xm/RU7gFS/0kM5TBSAQDry8y40Aez0ASY+3boUhv+3QE5XbOXiXM2JjdhkKve3IsBvWCibQ==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/convict/-/convict-6.2.2.tgz", + "integrity": "sha512-3MsROJiEFN3BAzeFit1t87t7EUFzd44MNd13MLSikV2dsnDl7znwKgtYPPONtnDzxiDW0nBAsxVhSRNrjUrTTg==", "dev": true, "dependencies": { "lodash.clonedeep": "^4.5.0", @@ -8925,9 +8968,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz", - "integrity": "sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz", + "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -15030,6 +15073,15 @@ "node": ">=0.10.0" } }, + "node_modules/loupe": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", + "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.0" + } + }, "node_modules/lower-case": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", @@ -15678,9 +15730,9 @@ } }, "node_modules/moment": { - "version": "2.29.2", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.2.tgz", - "integrity": "sha512-UgzG4rvxYpN15jgCmVJwac49h9ly9NurikMWGPdVxm8GZD6XjkKPxDTjQQ43gtGgnV3X0cAyWDdP2Wexoquifg==", + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", + "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==", "engines": { "node": "*" } @@ -17457,9 +17509,9 @@ } }, "node_modules/object-sizeof": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/object-sizeof/-/object-sizeof-1.6.1.tgz", - "integrity": "sha512-gNKGcRnDRXwEpAdwUY3Ef+aVZIrcQVXozSaVzHz6Pv4JxysH8vf5F+nIgsqW5T/YNwZNveh0mIW7PEH1O2MrDw==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/object-sizeof/-/object-sizeof-1.6.3.tgz", + "integrity": "sha512-LGtilAKuDGKCcvu1Xg3UvAhAeJJlFmblo3faltmOQ80xrGwAHxnauIXucalKdTEksHp/Pq9tZGz1hfyEmjFJPQ==", "dependencies": { "buffer": "^5.6.0" } @@ -19032,12 +19084,12 @@ } }, "node_modules/raw-body": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", - "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "dependencies": { - "bytes": "3.1.1", - "http-errors": "1.8.1", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, @@ -19045,19 +19097,27 @@ "node": ">= 0.8" } }, + "node_modules/raw-body/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/raw-body/node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dependencies": { - "depd": "~1.1.2", + "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", + "statuses": "2.0.1", "toidentifier": "1.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/raw-body/node_modules/setprototypeof": { @@ -19065,6 +19125,14 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "node_modules/raw-body/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/raw-body/node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -20390,7 +20458,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, "dependencies": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -22379,9 +22446,9 @@ } }, "node_modules/ts-node": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz", - "integrity": "sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==", + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", + "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", "dev": true, "dependencies": { "@cspotcode/source-map-support": "0.7.0", @@ -22395,11 +22462,13 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.0", "yn": "3.1.1" }, "bin": { "ts-node": "dist/bin.js", "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js", "ts-script": "dist/bin-script-deprecated.js" @@ -23151,6 +23220,12 @@ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, "node_modules/v8-to-istanbul": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", @@ -23326,13 +23401,13 @@ } }, "node_modules/webpack": { - "version": "5.67.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.67.0.tgz", - "integrity": "sha512-LjFbfMh89xBDpUMgA1W9Ur6Rn/gnr2Cq1jjHFPo4v6a79/ypznSYbAyPgGhwsxBtMIaEmDD1oJoA7BEYw/Fbrw==", + "version": "5.72.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.0.tgz", + "integrity": "sha512-qmSmbspI0Qo5ld49htys8GY9XhS9CGqFoHTsOVAnjBdg0Zn79y135R+k4IR4rKK6+eKaabMhJwiVB7xw0SJu5w==", "dev": true, "dependencies": { - "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.50", + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1", @@ -23340,7 +23415,7 @@ "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.8.3", + "enhanced-resolve": "^5.9.2", "es-module-lexer": "^0.9.0", "eslint-scope": "5.1.1", "events": "^3.2.0", @@ -23373,15 +23448,15 @@ } }, "node_modules/webpack-cli": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.1.tgz", - "integrity": "sha512-JYRFVuyFpzDxMDB+v/nanUdQYcZtqFPGzmlW4s+UkPMFhSpfRNmf1z4AwYcHJVdvEFAM7FFCQdNTpsBYhDLusQ==", + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.2.tgz", + "integrity": "sha512-m3/AACnBBzK/kMTcxWHcZFPrw/eQuY4Df1TxvIWfWM2x7mRqBQCqKEd96oCUa9jkapLBaFfRce33eGDb4Pr7YQ==", "dev": true, "dependencies": { "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.1.0", - "@webpack-cli/info": "^1.4.0", - "@webpack-cli/serve": "^1.6.0", + "@webpack-cli/configtest": "^1.1.1", + "@webpack-cli/info": "^1.4.1", + "@webpack-cli/serve": "^1.6.1", "colorette": "^2.0.14", "commander": "^7.0.0", "execa": "^5.0.0", @@ -26749,9 +26824,9 @@ "dev": true }, "@types/eslint": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.28.2.tgz", - "integrity": "sha512-KubbADPkfoU75KgKeKLsFHXnU4ipH7wYg0TRT33NK3N3yiu7jlFAAoygIWBV+KbuHx/G+AvuGX6DllnK35gfJA==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz", + "integrity": "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==", "dev": true, "requires": { "@types/estree": "*", @@ -26759,9 +26834,9 @@ } }, "@types/eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha512-SCFeogqiptms4Fg29WpOTk5nHIzfpKCemSN63ksBQYKTcXoJEmJagV+DhVmbapZzY4/5YaOV1nZwrsU79fFm1g==", + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", "dev": true, "requires": { "@types/eslint": "*", @@ -26769,9 +26844,9 @@ } }, "@types/estree": { - "version": "0.0.50", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", - "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", "dev": true }, "@types/express": { @@ -27138,9 +27213,9 @@ "dev": true }, "@types/validator": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.0.tgz", - "integrity": "sha512-+jBxVvXVuggZOrm04NR8z+5+bgoW4VZyLzUO+hmPPW1mVFL/HaitLAkizfv4yg9TbG8lkfHWVMQ11yDqrVVCzA==", + "version": "13.7.2", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.2.tgz", + "integrity": "sha512-KFcchQ3h0OPQgFirBRPZr5F/sVjxZsOrQHedj3zi8AH3Zv/hOLx2OLR4hxR5HcfoU+33n69ZuOfzthKVdMoTiw==", "dev": true }, "@types/webgl-ext": { @@ -27443,25 +27518,25 @@ } }, "@webpack-cli/configtest": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.0.tgz", - "integrity": "sha512-ttOkEkoalEHa7RaFYpM0ErK1xc4twg3Am9hfHhL7MVqlHebnkYd2wuI/ZqTDj0cVzZho6PdinY0phFZV3O0Mzg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.1.tgz", + "integrity": "sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg==", "dev": true, "requires": {} }, "@webpack-cli/info": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.0.tgz", - "integrity": "sha512-F6b+Man0rwE4n0409FyAJHStYA5OIZERxmnUfLVwv0mc0V1wLad3V7jqRlMkgKBeAq07jUvglacNaa6g9lOpuw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.1.tgz", + "integrity": "sha512-PKVGmazEq3oAo46Q63tpMr4HipI3OPfP7LiNOEJg963RMgT0rqheag28NCML0o3GIzA3DmxP1ZIAv9oTX1CUIA==", "dev": true, "requires": { "envinfo": "^7.7.3" } }, "@webpack-cli/serve": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.0.tgz", - "integrity": "sha512-ZkVeqEmRpBV2GHvjjUZqEai2PpUbuq8Bqd//vEYsp63J8WyexI8ppCqVS3Zs0QADf6aWuPdU+0XsPI647PVlQA==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.1.tgz", + "integrity": "sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw==", "dev": true, "requires": {} }, @@ -27812,9 +27887,9 @@ } }, "ajv": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz", - "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "requires": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -28527,20 +28602,22 @@ "dev": true }, "body-parser": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz", - "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", "requires": { - "bytes": "3.1.1", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.6", - "raw-body": "2.4.2", - "type-is": "~1.6.18" + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "dependencies": { "debug": { @@ -28551,15 +28628,25 @@ "ms": "2.0.0" } }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, "http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "requires": { - "depd": "~1.1.2", + "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", + "statuses": "2.0.1", "toidentifier": "1.0.1" } }, @@ -28568,16 +28655,32 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, "qs": { - "version": "6.9.6", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", - "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==" + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "requires": { + "side-channel": "^1.0.4" + } }, "setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, "toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -28998,9 +29101,9 @@ } }, "bytes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", - "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" }, "cacheable-request": { "version": "6.1.0", @@ -29201,15 +29304,16 @@ "dev": true }, "chai": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", - "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", + "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", "dev": true, "requires": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", "deep-eql": "^3.0.1", "get-func-name": "^2.0.0", + "loupe": "^2.3.1", "pathval": "^1.1.1", "type-detect": "^4.0.5" } @@ -29782,9 +29886,9 @@ "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=" }, "convict": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/convict/-/convict-6.2.1.tgz", - "integrity": "sha512-Mn4AJiYkR3TAZH1Xm/RU7gFS/0kM5TBSAQDry8y40Aez0ASY+3boUhv+3QE5XbOXiXM2JjdhkKve3IsBvWCibQ==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/convict/-/convict-6.2.2.tgz", + "integrity": "sha512-3MsROJiEFN3BAzeFit1t87t7EUFzd44MNd13MLSikV2dsnDl7znwKgtYPPONtnDzxiDW0nBAsxVhSRNrjUrTTg==", "dev": true, "requires": { "lodash.clonedeep": "^4.5.0", @@ -31172,9 +31276,9 @@ } }, "enhanced-resolve": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz", - "integrity": "sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz", + "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==", "dev": true, "requires": { "graceful-fs": "^4.2.4", @@ -35985,6 +36089,15 @@ "signal-exit": "^3.0.0" } }, + "loupe": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", + "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", + "dev": true, + "requires": { + "get-func-name": "^2.0.0" + } + }, "lower-case": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", @@ -36537,9 +36650,9 @@ } }, "moment": { - "version": "2.29.2", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.2.tgz", - "integrity": "sha512-UgzG4rvxYpN15jgCmVJwac49h9ly9NurikMWGPdVxm8GZD6XjkKPxDTjQQ43gtGgnV3X0cAyWDdP2Wexoquifg==" + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", + "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==" }, "moment-duration-format": { "version": "2.3.2", @@ -37967,9 +38080,9 @@ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, "object-sizeof": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/object-sizeof/-/object-sizeof-1.6.1.tgz", - "integrity": "sha512-gNKGcRnDRXwEpAdwUY3Ef+aVZIrcQVXozSaVzHz6Pv4JxysH8vf5F+nIgsqW5T/YNwZNveh0mIW7PEH1O2MrDw==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/object-sizeof/-/object-sizeof-1.6.3.tgz", + "integrity": "sha512-LGtilAKuDGKCcvu1Xg3UvAhAeJJlFmblo3faltmOQ80xrGwAHxnauIXucalKdTEksHp/Pq9tZGz1hfyEmjFJPQ==", "requires": { "buffer": "^5.6.0" }, @@ -39193,25 +39306,30 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", - "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "requires": { - "bytes": "3.1.1", - "http-errors": "1.8.1", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, "http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "requires": { - "depd": "~1.1.2", + "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", + "statuses": "2.0.1", "toidentifier": "1.0.1" } }, @@ -39220,6 +39338,11 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, "toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -40313,7 +40436,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, "requires": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -41931,9 +42053,9 @@ } }, "ts-node": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz", - "integrity": "sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==", + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", + "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", "dev": true, "requires": { "@cspotcode/source-map-support": "0.7.0", @@ -41947,6 +42069,7 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.0", "yn": "3.1.1" }, "dependencies": { @@ -42549,6 +42672,12 @@ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, "v8-to-istanbul": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", @@ -42701,13 +42830,13 @@ "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" }, "webpack": { - "version": "5.67.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.67.0.tgz", - "integrity": "sha512-LjFbfMh89xBDpUMgA1W9Ur6Rn/gnr2Cq1jjHFPo4v6a79/ypznSYbAyPgGhwsxBtMIaEmDD1oJoA7BEYw/Fbrw==", + "version": "5.72.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.0.tgz", + "integrity": "sha512-qmSmbspI0Qo5ld49htys8GY9XhS9CGqFoHTsOVAnjBdg0Zn79y135R+k4IR4rKK6+eKaabMhJwiVB7xw0SJu5w==", "dev": true, "requires": { - "@types/eslint-scope": "^3.7.0", - "@types/estree": "^0.0.50", + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1", @@ -42715,7 +42844,7 @@ "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.8.3", + "enhanced-resolve": "^5.9.2", "es-module-lexer": "^0.9.0", "eslint-scope": "5.1.1", "events": "^3.2.0", @@ -42748,15 +42877,15 @@ } }, "webpack-cli": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.1.tgz", - "integrity": "sha512-JYRFVuyFpzDxMDB+v/nanUdQYcZtqFPGzmlW4s+UkPMFhSpfRNmf1z4AwYcHJVdvEFAM7FFCQdNTpsBYhDLusQ==", + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.2.tgz", + "integrity": "sha512-m3/AACnBBzK/kMTcxWHcZFPrw/eQuY4Df1TxvIWfWM2x7mRqBQCqKEd96oCUa9jkapLBaFfRce33eGDb4Pr7YQ==", "dev": true, "requires": { "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.1.0", - "@webpack-cli/info": "^1.4.0", - "@webpack-cli/serve": "^1.6.0", + "@webpack-cli/configtest": "^1.1.1", + "@webpack-cli/info": "^1.4.1", + "@webpack-cli/serve": "^1.6.1", "colorette": "^2.0.14", "commander": "^7.0.0", "execa": "^5.0.0", diff --git a/package.json b/package.json index 32972e747a..49c55e1e1a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ev-server", - "version": "2.6.5", + "version": "2.6.6", "engines": { "node": "16.x.x", "npm": "8.x.x" @@ -87,7 +87,7 @@ "test:user": "npm version && cross-env TS_NODE_FILES=true jest --config='./test/jest.config.ts' --runInBand --logHeapUsage --verbose --colors --silent -- test/**/UserTest.ts" }, "dependencies": { - "ajv": "^8.6.3", + "ajv": "^8.11.0", "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0", "axios": "^0.25.0", @@ -95,7 +95,7 @@ "basic-auth": "^2.0.1", "bcryptjs": "^2.4.3", "bluebird": "^3.7.2", - "body-parser": "^1.19.1", + "body-parser": "^1.20.0", "body-parser-xml": "^2.0.3", "busboy": "^1.4.0", "chalk": "^4.1.2", @@ -121,7 +121,7 @@ "jsonwebtoken": "^8.5.1", "locale": "^0.1.0", "lodash": "^4.17.21", - "moment": "^2.29.2", + "moment": "^2.29.3", "moment-duration-format": "^2.3.2", "moment-timezone": "^0.5.34", "mongo-sanitize": "^1.1.0", @@ -131,7 +131,7 @@ "mustache": "^4.2.0", "nanoid": "^3.2.0", "node-cron": "^3.0.0", - "object-sizeof": "^1.6.1", + "object-sizeof": "^1.6.3", "passport": "^0.5.2", "passport-jwt": "^4.0.0", "password-generator": "^2.3.2", @@ -197,18 +197,18 @@ "@types/tz-lookup": "^6.1.0", "@types/urlencode": "^1.1.2", "@types/uuid": "^8.3.4", - "@types/validator": "^13.7.0", + "@types/validator": "^13.7.2", "@types/ws": "^8.2.2", "@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/parser": "^4.32.0", "autocannon": "^7.6.0", - "chai": "^4.3.4", + "chai": "^4.3.6", "chai-datetime": "^1.8.0", "chai-subset": "^1.6.0", "circular-dependency-plugin": "^5.2.2", "clean-webpack-plugin": "^4.0.0", "clinic": "^10.0.0", - "convict": "^6.2.0", + "convict": "^6.2.2", "copy-webpack-plugin": "^9.0.1", "cross-env": "^7.0.3", "deep-object-diff": "^1.1.0", @@ -228,11 +228,11 @@ "rosie": "^2.1.0", "ts-jest": "^27.1.3", "ts-loader": "^9.2.6", - "ts-node": "^10.3.0", + "ts-node": "^10.7.0", "ts-node-dev": "^1.1.8", "typescript": "^4.5.4", - "webpack": "^5.67.0", - "webpack-cli": "^4.9.1", + "webpack": "^5.72.0", + "webpack-cli": "^4.9.2", "webpack-merge": "^5.8.0", "webpack-node-externals": "^3.0.0", "webpack-shell-plugin-next": "^2.2.2", diff --git a/postman/EVSE.postman_collection.json b/postman/EVSE.postman_collection.json index fefe919baf..7870a5374e 100644 --- a/postman/EVSE.postman_collection.json +++ b/postman/EVSE.postman_collection.json @@ -6420,14 +6420,14 @@ "method": "GET", "header": [], "url": { - "raw": "{{base_url}}/v1/api/loggings?Limit=100", + "raw": "{{base_url}}/v1/api/logs?Limit=100", "host": [ "{{base_url}}" ], "path": [ "v1", "api", - "loggings" + "logs" ], "query": [ { @@ -6520,14 +6520,14 @@ "method": "GET", "header": [], "url": { - "raw": "{{base_url}}/v1/api/loggings/{{logID}}", + "raw": "{{base_url}}/v1/api/logs/{{logID}}", "host": [ "{{base_url}}" ], "path": [ "v1", "api", - "loggings", + "logs", "{{logID}}" ] } @@ -6695,14 +6695,14 @@ "method": "GET", "header": [], "url": { - "raw": "{{base_url}}/v1/api/loggings/action/export", + "raw": "{{base_url}}/v1/api/logs/action/export", "host": [ "{{base_url}}" ], "path": [ "v1", "api", - "loggings", + "logs", "action", "export" ], diff --git a/src/assets/charging-station-templates b/src/assets/charging-station-templates index fa15440c76..748b8369c5 160000 --- a/src/assets/charging-station-templates +++ b/src/assets/charging-station-templates @@ -1 +1 @@ -Subproject commit fa15440c7682ec2fb90e6a7f871210dd8a7ba0ab +Subproject commit 748b8369c5925f0ad4d842525df3757115998f46 diff --git a/src/assets/config-template-http.json b/src/assets/config-template-http.json index 20d2d58cd0..11a9e2cf00 100644 --- a/src/assets/config-template-http.json +++ b/src/assets/config-template-http.json @@ -105,8 +105,7 @@ "authURI": "", "tokenURI": "", "authProviderX509CertURL": "", - "clientX509CertURL": "", - "databaseURL": "" + "clientX509CertURL": "" }, "Axios": { "retries": 0, diff --git a/src/assets/config-template-https.json b/src/assets/config-template-https.json index 1aea1e46d2..721760a74c 100644 --- a/src/assets/config-template-https.json +++ b/src/assets/config-template-https.json @@ -119,8 +119,7 @@ "authURI": "", "tokenURI": "", "authProviderX509CertURL": "", - "clientX509CertURL": "", - "databaseURL": "" + "clientX509CertURL": "" }, "Axios": { "retries": 0, diff --git a/src/assets/configs-aws b/src/assets/configs-aws index 5f27c68e14..494057acab 160000 --- a/src/assets/configs-aws +++ b/src/assets/configs-aws @@ -1 +1 @@ -Subproject commit 5f27c68e143a3cb5b55ad665f509b25d7bd6ad53 +Subproject commit 494057acab3c97ddc21df9421cdc8805d36de824 diff --git a/src/assets/configs-ci b/src/assets/configs-ci index 33e5ca034c..0ce7ed98a3 160000 --- a/src/assets/configs-ci +++ b/src/assets/configs-ci @@ -1 +1 @@ -Subproject commit 33e5ca034cb869aead22e37d1cbabd512ebfda95 +Subproject commit 0ce7ed98a322e889247957b6eeba63416b06ded4 diff --git a/src/assets/schemas/configuration/configuration.json b/src/assets/schemas/configuration/configuration.json index e065ec015a..f41b3a9387 100644 --- a/src/assets/schemas/configuration/configuration.json +++ b/src/assets/schemas/configuration/configuration.json @@ -402,9 +402,6 @@ "clientX509CertURL": { "type": "string" }, - "databaseURL": { - "type": "string" - }, "tenants": { "type": "array", "items": { @@ -434,8 +431,7 @@ "authURI", "tokenURI", "authProviderX509CertURL", - "clientX509CertURL", - "databaseURL" + "clientX509CertURL" ] }, "Axios": { diff --git a/src/assets/schemas/user/user.json b/src/assets/schemas/user/user.json index 889391c413..719b41d065 100644 --- a/src/assets/schemas/user/user.json +++ b/src/assets/schemas/user/user.json @@ -39,7 +39,8 @@ }, "mobile": { "type": "string", - "sanitize": "mongo" + "sanitize": "mongo", + "pattern": "^\\+?([0-9] ?){9,14}[0-9]$" }, "locale": { "type": "string", @@ -50,7 +51,8 @@ }, "phone": { "type": "string", - "sanitize": "mongo" + "sanitize": "mongo", + "pattern": "^\\+?([0-9] ?){9,14}[0-9]$" }, "issuer": { "type": "boolean", @@ -66,7 +68,8 @@ }, "plateID": { "type": "string", - "sanitize": "mongo" + "sanitize": "mongo", + "pattern": "^[A-Z0-9- ]*$" }, "role": { "type": "string", diff --git a/src/assets/server/notification/email/en/compute-and-apply-charging-profiles-failed.json b/src/assets/server/notification/email/en/compute-and-apply-charging-profiles-failed.json index 69ad5b5b95..bf5d10f962 100644 --- a/src/assets/server/notification/email/en/compute-and-apply-charging-profiles-failed.json +++ b/src/assets/server/notification/email/en/compute-and-apply-charging-profiles-failed.json @@ -19,7 +19,7 @@ "beforeActionLines": [ "Dear Administrator,", "", - "Applying the charging profiles for '<%- chargeBoxID %>' failed three times.", + "Applying the charging profiles for '<%- chargeBoxID %>' failed.", "", "The charging station was excluded from this smart charging run automatically." ], diff --git a/src/assets/server/notification/email/es/compute-and-apply-charging-profiles-failed.json b/src/assets/server/notification/email/es/compute-and-apply-charging-profiles-failed.json index 628a1cf597..f7938c8bec 100644 --- a/src/assets/server/notification/email/es/compute-and-apply-charging-profiles-failed.json +++ b/src/assets/server/notification/email/es/compute-and-apply-charging-profiles-failed.json @@ -19,7 +19,7 @@ "beforeActionLines": [ "Dear Administrator,", "", - "Applying the charging profiles for '<%- chargeBoxID %>' failed three times.", + "Applying the charging profiles for '<%- chargeBoxID %>' failed.", "", "The charging station was excluded from smart charging management automatically." ], diff --git a/src/assets/server/notification/email/fr/compute-and-apply-charging-profiles-failed.json b/src/assets/server/notification/email/fr/compute-and-apply-charging-profiles-failed.json index f3b33530c2..8e1d76cd90 100644 --- a/src/assets/server/notification/email/fr/compute-and-apply-charging-profiles-failed.json +++ b/src/assets/server/notification/email/fr/compute-and-apply-charging-profiles-failed.json @@ -19,7 +19,7 @@ "beforeActionLines": [ "Cher Administrateur,", "", - "Les profils de charge envoyés à '<%- chargeBoxID %>' ont échoué trois fois.", + "Les profils de charge envoyés à '<%- chargeBoxID %>' ont échoué.", "", "Cette borne a donc été exclue de la gestion de la charge intelligente automatiquement." ], diff --git a/src/assets/server/notification/email/it/compute-and-apply-charging-profiles-failed.json b/src/assets/server/notification/email/it/compute-and-apply-charging-profiles-failed.json index b43eb644d5..ab416f91a0 100644 --- a/src/assets/server/notification/email/it/compute-and-apply-charging-profiles-failed.json +++ b/src/assets/server/notification/email/it/compute-and-apply-charging-profiles-failed.json @@ -19,7 +19,7 @@ "beforeActionLines": [ "Gentile Amministratore,", "", - "Applicazione dei profili di ricarica per '<%- chargeBoxID %>' è fallita tre volte.", + "Applicazione dei profili di ricarica per '<%- chargeBoxID %>' è fallita.", "", "La stazione di ricarica è stata esclusa automaticamente dalla gestione della ricarica intelligente." ], diff --git a/src/assets/server/notification/email/pt/compute-and-apply-charging-profiles-failed.json b/src/assets/server/notification/email/pt/compute-and-apply-charging-profiles-failed.json index 628a1cf597..f7938c8bec 100644 --- a/src/assets/server/notification/email/pt/compute-and-apply-charging-profiles-failed.json +++ b/src/assets/server/notification/email/pt/compute-and-apply-charging-profiles-failed.json @@ -19,7 +19,7 @@ "beforeActionLines": [ "Dear Administrator,", "", - "Applying the charging profiles for '<%- chargeBoxID %>' failed three times.", + "Applying the charging profiles for '<%- chargeBoxID %>' failed.", "", "The charging station was excluded from smart charging management automatically." ], diff --git a/src/assets/server/ocpp/schemas/authorize-request.json b/src/assets/server/ocpp/schemas/authorize-request.json index 22da14bd7f..cf7ecd5cd8 100644 --- a/src/assets/server/ocpp/schemas/authorize-request.json +++ b/src/assets/server/ocpp/schemas/authorize-request.json @@ -1,6 +1,6 @@ { "$id": "authorize-request", - "description": "Defines the Authorize.req PDU", + "description": "AuthorizeRequest", "type": "object", "properties": { "idTag": { diff --git a/src/assets/server/ocpp/schemas/boot-notification-request.json b/src/assets/server/ocpp/schemas/boot-notification-request.json index a65b9516e2..90bff2edc6 100644 --- a/src/assets/server/ocpp/schemas/boot-notification-request.json +++ b/src/assets/server/ocpp/schemas/boot-notification-request.json @@ -1,6 +1,6 @@ { "$id": "boot-notification-request", - "description": "Defines the BootNotification.req PDU", + "description": "BootNotificationRequest", "type": "object", "properties": { "chargePointVendor": { diff --git a/src/assets/server/ocpp/schemas/heartbeat-request.json b/src/assets/server/ocpp/schemas/heartbeat-request.json index 3ce4a33399..8e72739fcf 100644 --- a/src/assets/server/ocpp/schemas/heartbeat-request.json +++ b/src/assets/server/ocpp/schemas/heartbeat-request.json @@ -1,6 +1,6 @@ { "$id": "heartbeat-request", - "title": "HeartbeatResponse", + "title": "HeartbeatRequest", "type": "object", "properties": {}, "additionalProperties": false diff --git a/src/assets/server/ocpp/schemas/meter-values-request.json b/src/assets/server/ocpp/schemas/meter-values-request.json new file mode 100644 index 0000000000..98cabb22d5 --- /dev/null +++ b/src/assets/server/ocpp/schemas/meter-values-request.json @@ -0,0 +1,293 @@ +{ + "$id": "meter-values-request", + "title": "MeterValuesRequest", + "type": "object", + "properties": { + "connectorId": { + "type": "integer", + "default": 0 + }, + "transactionId": { + "type": "integer" + }, + "meterValue": { + "oneOf": [ + { + "$ref": "#/definitions/meterValueOCPP16" + }, + { + "$ref": "#/definitions/meterValuesOCPP16" + } + ] + }, + "values": { + "oneOf": [ + { + "$ref": "#/definitions/meterValueOCPP15" + }, + { + "$ref": "#/definitions/meterValuesOCPP15" + } + ] + } + }, + "required": [ + "connectorId" + ], + "oneOf": [ + { + "required": [ + "meterValue" + ] + }, + { + "required": [ + "values" + ] + } + ], + "definitions": { + "meterValueOCPP16": { + "type": "object", + "properties": { + "timestamp": { + "type": "string", + "format": "date-time" + }, + "sampledValue": { + "type": "array", + "items": { + "type": "object", + "properties": { + "value": { + "type": "string" + }, + "measurand": { + "type": "string", + "default": "Energy.Active.Import.Register", + "enum": [ + "Energy.Active.Export.Register", + "Energy.Active.Import.Register", + "Energy.Reactive.Export.Register", + "Energy.Reactive.Import.Register", + "Energy.Active.Export.Interval", + "Energy.Active.Import.Interval", + "Energy.Reactive.Export.Interval", + "Energy.Reactive.Import.Interval", + "Power.Active.Export", + "Power.Active.Import", + "Power.Offered", + "Power.Reactive.Export", + "Power.Reactive.Import", + "Power.Factor", + "Current.Import", + "Current.Export", + "Current.Offered", + "Voltage", + "Frequency", + "Temperature", + "SoC", + "RPM" + ] + }, + "context": { + "type": "string", + "default": "Sample.Periodic", + "enum": [ + "Interruption.Begin", + "Interruption.End", + "Sample.Clock", + "Sample.Periodic", + "Transaction.Begin", + "Transaction.End", + "Trigger", + "Other" + ] + }, + "location": { + "type": "string", + "default": "Outlet", + "enum": [ + "Cable", + "EV", + "Inlet", + "Outlet", + "Body" + ] + }, + "unit": { + "type": "string", + "default": "Wh", + "enum": [ + "Wh", + "kWh", + "varh", + "kvarh", + "W", + "kW", + "VA", + "kVA", + "var", + "kvar", + "A", + "V", + "K", + "Celcius", + "Fahrenheit", + "Percent" + ] + }, + "phase": { + "type": "string", + "enum": [ + "L1", + "L2", + "L3", + "N", + "L1-N", + "L2-N", + "L3-N", + "L1-L2", + "L2-L3", + "L3-L1" + ] + }, + "format": { + "type": "string", + "default": "Raw", + "enum": [ + "Raw", + "SignedData" + ] + } + }, + "required": [ + "value" + ] + } + } + }, + "required": [ + "timestamp", + "sampledValue" + ] + }, + "meterValuesOCPP16": { + "type": "array", + "items": { + "$ref": "#/definitions/meterValueOCPP16/properties" + } + }, + "meterValueOCPP15": { + "type": "object", + "properties": { + "timestamp": { + "type": "string", + "format": "date-time" + }, + "value": { + "type": "object", + "properties": { + "$value": { + "type": "string" + }, + "attributes": { + "type": "object", + "properties": { + "measurand": { + "type": "string", + "default": "Energy.Active.Import.Register", + "enum": [ + "Energy.Active.Export.Register", + "Energy.Active.Import.Register", + "Energy.Reactive.Export.Register", + "Energy.Reactive.Import.Register", + "Energy.Active.Export.Interval", + "Energy.Active.Import.Interval", + "Energy.Reactive.Export.Interval", + "Energy.Reactive.Import.Interval", + "Power.Active.Export", + "Power.Active.Import", + "Power.Reactive.Export", + "Power.Reactive.Import", + "Current.Import", + "Current.Export", + "Voltage", + "Temperature" + ] + }, + "context": { + "type": "string", + "enum": [ + "Interruption.Begin", + "Interruption.End", + "Sample.Clock", + "Sample.Periodic", + "Transaction.Begin", + "Transaction.End", + "Trigger", + "Other" + ] + }, + "location": { + "type": "string", + "default": "Outlet", + "enum": [ + "Cable", + "EV", + "Inlet", + "Outlet", + "Body" + ] + }, + "unit": { + "type": "string", + "default": "Wh", + "enum": [ + "Wh", + "kWh", + "varh", + "kvarh", + "W", + "kW", + "VA", + "kVA", + "var", + "kvar", + "A", + "V", + "K", + "Celcius", + "Fahrenheit", + "Percent" + ] + }, + "format": { + "type": "string", + "default": "Raw", + "enum": [ + "Raw", + "SignedData" + ] + } + } + } + }, + "required": [ + "$value" + ] + } + }, + "required": [ + "timestamp", + "value" + ] + }, + "meterValuesOCPP15": { + "type": "array", + "items": { + "$ref": "#/definitions/meterValueOCPP15/properties" + } + } + } +} \ No newline at end of file diff --git a/src/assets/server/ocpp/schemas/start-transaction-request.json b/src/assets/server/ocpp/schemas/start-transaction-request.json index c81f97e8fa..c5fe0e5a35 100644 --- a/src/assets/server/ocpp/schemas/start-transaction-request.json +++ b/src/assets/server/ocpp/schemas/start-transaction-request.json @@ -1,6 +1,6 @@ { "$id": "start-transaction-request", - "description": "Defines the StartTransaction.req PDU", + "description": "StartTransactionRequest", "type": "object", "properties": { "connectorId": { diff --git a/src/assets/server/ocpp/schemas/status-notification-request.json b/src/assets/server/ocpp/schemas/status-notification-request.json index e88d8d0517..22da594207 100644 --- a/src/assets/server/ocpp/schemas/status-notification-request.json +++ b/src/assets/server/ocpp/schemas/status-notification-request.json @@ -1,6 +1,6 @@ { "$id": "status-notification-request", - "description": "Defines the StatusNotification.req PDU", + "description": "StatusNotificationRequest", "type": "object", "properties": { "connectorId": { diff --git a/src/assets/server/ocpp/schemas/stop-transaction-request-15.json b/src/assets/server/ocpp/schemas/stop-transaction-request-15.json index 7ab05db989..3a490f34ca 100644 --- a/src/assets/server/ocpp/schemas/stop-transaction-request-15.json +++ b/src/assets/server/ocpp/schemas/stop-transaction-request-15.json @@ -1,6 +1,6 @@ { "$id": "stop-transaction-request-15", - "description": "Defines the StopTransaction.req PDU for OCPP 1.5", + "description": "StopTransactionRequest 1.5", "type": "object", "properties": { "transactionId": { diff --git a/src/assets/server/ocpp/schemas/stop-transaction-request-16.json b/src/assets/server/ocpp/schemas/stop-transaction-request-16.json index 079c320273..989fda1e70 100644 --- a/src/assets/server/ocpp/schemas/stop-transaction-request-16.json +++ b/src/assets/server/ocpp/schemas/stop-transaction-request-16.json @@ -1,6 +1,6 @@ { - "$id": "stop-transaction-request", - "description": "Defines the StopTransaction.req PDU for OCPP 1.6", + "$id": "stop-transaction-request-16", + "description": "StopTransactionRequest 1.6", "type": "object", "properties": { "transactionId": { diff --git a/src/assets/server/rest/v1/docs/e-mobility-oas.json b/src/assets/server/rest/v1/docs/e-mobility-oas.json index 74aa60cc0e..019a36b234 100644 --- a/src/assets/server/rest/v1/docs/e-mobility-oas.json +++ b/src/assets/server/rest/v1/docs/e-mobility-oas.json @@ -48,8 +48,8 @@ "description": "Integration connection API" }, { - "name": "Loggings", - "description": "Loggings API" + "name": "Logs", + "description": "Logs API" }, { "name": "Assets", @@ -4690,12 +4690,12 @@ }, "startTime": { "type": "string", - "description": "Optional. This contains the date and time of the oldest logging information to include in the diagnostics.", + "description": "Optional. This contains the date and time of the oldest log information to include in the diagnostics.", "format": "date-time" }, "stopTime": { "type": "string", - "description": "Optional. This contains the date and time of the latest logging information to include in the diagnostics.", + "description": "Optional. This contains the date and time of the latest log information to include in the diagnostics.", "format": "date-time" } }, @@ -7428,12 +7428,6 @@ "parameters": [ { "$ref": "#/components/parameters/userID" - }, - { - "$ref": "#/components/parameters/Skip" - }, - { - "$ref": "#/components/parameters/Limit" } ], "tags": [ @@ -9067,7 +9061,7 @@ } } }, - "/api/loggings": { + "/api/logs": { "get": { "security": [ { @@ -9123,7 +9117,7 @@ } ], "tags": [ - "Loggings" + "Logs" ], "responses": { "200": { @@ -9168,7 +9162,7 @@ } } }, - "/api/loggings/{id}": { + "/api/logs/{id}": { "get": { "security": [ { @@ -9188,7 +9182,7 @@ } ], "tags": [ - "Loggings" + "Logs" ], "responses": { "200": { @@ -9230,14 +9224,14 @@ } } }, - "/api/loggings/action/export": { + "/api/logs/action/export": { "get": { "security": [ { "bearerAuth": [] } ], - "description": "Export loggings as CSV file", + "description": "Export logs as CSV file", "parameters": [ { "$ref": "#/components/parameters/StartDateTime" @@ -9283,7 +9277,7 @@ } ], "tags": [ - "Loggings" + "Logs" ], "responses": { "200": { diff --git a/src/assets/server/rest/v1/schemas/asset/asset-create.json b/src/assets/server/rest/v1/schemas/asset/asset-create.json index 024abf495c..e84fa20051 100644 --- a/src/assets/server/rest/v1/schemas/asset/asset-create.json +++ b/src/assets/server/rest/v1/schemas/asset/asset-create.json @@ -1,6 +1,6 @@ { "$id": "asset-create", - "title": "Create Asset Request", + "title": "Create Asset Request", "type": "object", "properties": { "name": { diff --git a/src/assets/server/rest/v1/schemas/logging/logging-get.json b/src/assets/server/rest/v1/schemas/log/log-get.json similarity index 75% rename from src/assets/server/rest/v1/schemas/logging/logging-get.json rename to src/assets/server/rest/v1/schemas/log/log-get.json index f59102ab2f..c8ab1ddd02 100644 --- a/src/assets/server/rest/v1/schemas/logging/logging-get.json +++ b/src/assets/server/rest/v1/schemas/log/log-get.json @@ -1,6 +1,6 @@ { - "$id": "logging-get", - "title": "Get Logging", + "$id": "log-get", + "title": "Get Log", "description": "", "type": "object", "properties": { diff --git a/src/assets/server/rest/v1/schemas/logging/loggings-get.json b/src/assets/server/rest/v1/schemas/log/logs-get.json similarity index 96% rename from src/assets/server/rest/v1/schemas/logging/loggings-get.json rename to src/assets/server/rest/v1/schemas/log/logs-get.json index 189893a581..b46cf648ed 100644 --- a/src/assets/server/rest/v1/schemas/logging/loggings-get.json +++ b/src/assets/server/rest/v1/schemas/log/logs-get.json @@ -1,6 +1,6 @@ { - "$id": "loggings-get", - "title": "Get Loggings", + "$id": "logs-get", + "title": "Get Logs", "type": "object", "properties": { "StartDateTime": { diff --git a/src/authorization/AuthorizationsDefinition.ts b/src/authorization/AuthorizationsDefinition.ts index c4a1e17b2f..7fe7107097 100644 --- a/src/authorization/AuthorizationsDefinition.ts +++ b/src/authorization/AuthorizationsDefinition.ts @@ -7,8 +7,8 @@ export const AUTHORIZATION_DEFINITION: AuthorizationDefinition = { { resource: Entity.USER, action: Action.LIST, attributes: [ - 'id', 'name', 'firstName', 'email', 'role', 'status', 'issuer', 'createdOn', 'createdBy', - 'lastChangedOn', 'lastChangedBy', 'eulaAcceptedOn', 'eulaAcceptedVersion', 'locale', + 'id', 'name', 'firstName', 'email', 'role', 'status', 'issuer', 'createdOn', 'createdBy.name', 'createdBy.firstName', + 'lastChangedOn', 'lastChangedBy.name', 'lastChangedBy.firstName', 'eulaAcceptedOn', 'eulaAcceptedVersion', 'locale', 'billingData.customerID', 'billingData.lastChangedOn' ], condition: { @@ -104,8 +104,8 @@ export const AUTHORIZATION_DEFINITION: AuthorizationDefinition = { Action.LIST, Action.EXPORT, Action.IMPORT ], attributes: [ - 'id', 'name', 'firstName', 'email', 'role', 'status', 'issuer', 'createdOn', 'createdBy', - 'lastChangedOn', 'lastChangedBy', 'eulaAcceptedOn', 'eulaAcceptedVersion', 'locale', + 'id', 'name', 'firstName', 'email', 'role', 'status', 'issuer', 'createdOn', 'createdBy.name', 'createdBy.firstName', + 'lastChangedOn', 'lastChangedBy.name', 'lastChangedBy.firstName', 'eulaAcceptedOn', 'eulaAcceptedVersion', 'locale', 'billingData.customerID', 'billingData.lastChangedOn', 'technical', 'freeAccess' ], condition: { @@ -274,7 +274,8 @@ export const AUTHORIZATION_DEFINITION: AuthorizationDefinition = { attributes: [ 'id', 'name', 'siteID', 'maximumPower', 'voltage', 'numberOfPhases', 'accessControl', 'smartCharging', 'address.address1', 'address.address2', 'address.postalCode', 'address.city', 'address.country', - 'address.coordinates', 'site.id', 'site.name', 'site.public', 'issuer', 'distanceMeters', 'createdOn', 'createdBy', 'lastChangedOn', 'lastChangedBy' + 'address.coordinates', 'site.id', 'site.name', 'site.public', 'issuer', 'distanceMeters', 'createdOn', 'createdBy.name', 'createdBy.firstName', 'lastChangedOn', + 'lastChangedBy.name', 'lastChangedBy.firstName' ] }, { @@ -374,13 +375,15 @@ export const AUTHORIZATION_DEFINITION: AuthorizationDefinition = { }, { resource: Entity.BILLING, action: [Action.CHECK_CONNECTION, Action.CLEAR_BILLING_TEST_DATA] }, { resource: Entity.TAX, action: [Action.LIST] }, - // --------------------------------------------------------------------------------------------------- - // TODO - no use-case so far - clarify whether a SYNC INVOICES and CREATE INVOICE makes sense or not! - // --------------------------------------------------------------------------------------------------- - // { resource: Entity.INVOICES, action: [Action.LIST, Action.SYNCHRONIZE] }, - // { resource: Entity.INVOICE, action: [Action.DOWNLOAD, Action.CREATE] }, - { resource: Entity.INVOICE, action: [Action.LIST] }, - { resource: Entity.INVOICE, action: [Action.DOWNLOAD, Action.READ] }, + { + resource: Entity.INVOICE, action: [Action.LIST], + attributes: [ + 'id', 'number', 'status', 'amount', 'createdOn', 'currency', 'downloadable', 'sessions', 'userID', 'user.id', 'user.name', 'user.firstName', 'user.email' + ] + }, + { + resource: Entity.INVOICE, action: [Action.DOWNLOAD, Action.READ] + }, { resource: Entity.ASSET, action: [Action.CREATE, Action.READ, Action.CHECK_CONNECTION, Action.CREATE_CONSUMPTION] @@ -664,9 +667,54 @@ export const AUTHORIZATION_DEFINITION: AuthorizationDefinition = { 'id', 'name', 'issuer', 'logo', 'address' ] }, - { resource: Entity.INVOICE, action: [Action.LIST] }, { - resource: Entity.INVOICE, action: [Action.DOWNLOAD, Action.READ], + resource: Entity.INVOICE, action: Action.LIST, + condition: { + Fn: 'custom:dynamicAuthorizations', + args: { + asserts: [], + filters: ['OwnUser'] + } + }, + attributes: [ + 'id', 'number', 'status', 'amount', 'createdOn', 'currency', 'downloadable', 'sessions' + ] + }, + { + resource: Entity.INVOICE, action: Action.READ, + condition: { + Fn: 'custom:dynamicAuthorizations', + args: { + asserts: [], + filters: ['OwnUser'] + } + }, + attributes: [ + 'id', 'number', 'status', 'amount', 'createdOn', 'currency', 'downloadable', 'sessions' + ] + }, + { + resource: Entity.INVOICE, action: Action.DOWNLOAD, + condition: { + Fn: 'custom:dynamicAuthorizations', + args: { + asserts: [], + filters: ['OwnUser'] + } + } + }, + { + resource: Entity.PAYMENT_METHOD, action: Action.LIST, + condition: { + Fn: 'custom:dynamicAuthorizations', + args: { + asserts: [], + filters: ['OwnUser'] + } + } + }, + { + resource: Entity.PAYMENT_METHOD, action: [Action.READ, Action.CREATE, Action.DELETE], condition: { Fn: 'custom:dynamicAuthorizations', args: { @@ -675,8 +723,6 @@ export const AUTHORIZATION_DEFINITION: AuthorizationDefinition = { } } }, - { resource: Entity.PAYMENT_METHOD, action: Action.LIST }, - { resource: Entity.PAYMENT_METHOD, action: [Action.READ, Action.CREATE, Action.DELETE] }, { resource: Entity.SITE, action: Action.LIST, condition: { diff --git a/src/client/ocpi/CpoOCPIClient.ts b/src/client/ocpi/CpoOCPIClient.ts index ee35082e24..2d9a020613 100644 --- a/src/client/ocpi/CpoOCPIClient.ts +++ b/src/client/ocpi/CpoOCPIClient.ts @@ -124,12 +124,14 @@ export default class CpoOCPIClient extends OCPIClient { // Update the tags await Promise.map(tokens, async (token) => { try { - // Get eMSP user - const email = OCPIUtils.buildEmspEmailFromOCPIToken(token, this.ocpiEndpoint.countryCode, this.ocpiEndpoint.partyId); + // Get eMSP user + const email = OCPIUtils.buildEmspEmailFromOCPIToken( + token, this.ocpiEndpoint.countryCode, this.ocpiEndpoint.partyId); const emspUser = emspUsersMap.get(email); // Get the Tag const emspTag = tags.result.find((tag) => tag.id === token.uid); - await OCPIUtilsService.updateCpoToken(this.tenant, token, emspTag, emspUser, ServerAction.OCPI_CPO_GET_TOKENS); + await OCPIUtilsService.updateCreateTagWithCpoToken( + this.tenant, token, emspTag, emspUser, ServerAction.OCPI_CPO_GET_TOKENS); result.success++; } catch (error) { result.failure++; @@ -171,10 +173,8 @@ export default class CpoOCPIClient extends OCPIClient { // Get tokens endpoint url const tokensUrl = `${this.getEndpointUrl('tokens', ServerAction.OCPI_CPO_AUTHORIZE_TOKEN)}/${token.uid}/authorize`; // Build payload - const locationReference: OCPILocationReference = - { + const locationReference: OCPILocationReference = { location_id: chargingStation.siteID, - // Gireve does not support authorization request on multiple EVSE evse_uids: [RoamingUtils.buildEvseUID(chargingStation, connector.connectorId)] }; // Call IOP @@ -243,7 +243,7 @@ export default class CpoOCPIClient extends OCPIClient { location: ocpiLocation, currency: this.settings.currency, status: OCPISessionStatus.PENDING, - total_cost: transaction.currentCumulatedPrice > 0 ? transaction.currentCumulatedPrice : 0, + total_cost: 0, // Never calculate the cost of OCPI transaction last_updated: transaction.timestamp }; // Call IOP @@ -284,7 +284,7 @@ export default class CpoOCPIClient extends OCPIClient { // Update transaction transaction.ocpiData.session.kwh = Utils.createDecimal(transaction.currentTotalConsumptionWh).div(1000).toNumber(); transaction.ocpiData.session.last_updated = transaction.currentTimestamp; - transaction.ocpiData.session.total_cost = transaction.currentCumulatedPrice > 0 ? transaction.currentCumulatedPrice : 0; + transaction.ocpiData.session.total_cost = 0; // Never calculate the cost of OCPI transaction transaction.ocpiData.session.currency = this.settings.currency; transaction.ocpiData.session.status = OCPISessionStatus.ACTIVE; transaction.ocpiData.session.charging_periods = await this.buildChargingPeriods(this.tenant, transaction); @@ -293,7 +293,7 @@ export default class CpoOCPIClient extends OCPIClient { kwh: transaction.ocpiData.session.kwh, last_updated: transaction.ocpiData.session.last_updated, currency: transaction.ocpiData.session.currency, - total_cost: transaction.ocpiData.session.total_cost > 0 ? transaction.ocpiData.session.total_cost : 0, + total_cost: 0, // Never calculate the cost of OCPI transaction status: transaction.ocpiData.session.status, charging_periods: transaction.ocpiData.session.charging_periods }; @@ -336,7 +336,7 @@ export default class CpoOCPIClient extends OCPIClient { // Get tokens endpoint url const tokensUrl = `${this.getEndpointUrl('sessions', ServerAction.OCPI_CPO_PUSH_SESSIONS)}/${this.getLocalCountryCode(ServerAction.OCPI_CPO_PUSH_SESSIONS)}/${this.getLocalPartyID(ServerAction.OCPI_CPO_PUSH_SESSIONS)}/${transaction.ocpiData.session.id}`; transaction.ocpiData.session.kwh = Utils.createDecimal(transaction.stop.totalConsumptionWh).div(1000).toNumber(); - transaction.ocpiData.session.total_cost = transaction.stop.roundedPrice > 0 ? transaction.stop.roundedPrice : 0; + transaction.ocpiData.session.total_cost = 0; // Never calculate the cost of OCPI transaction transaction.ocpiData.session.end_datetime = transaction.stop.timestamp; transaction.ocpiData.session.last_updated = transaction.stop.timestamp; transaction.ocpiData.session.status = OCPISessionStatus.COMPLETED; @@ -400,7 +400,7 @@ export default class CpoOCPIClient extends OCPIClient { auth_method: transaction.ocpiData.session.auth_method, location: transaction.ocpiData.session.location, authorization_id: transaction.ocpiData.session.authorization_id, - total_cost: transaction.stop.roundedPrice > 0 ? transaction.stop.roundedPrice : 0, + total_cost: 0, // Never calculate the cost of OCPI transaction charging_periods: await this.buildChargingPeriods(this.tenant, transaction), last_updated: transaction.stop.timestamp }; @@ -778,7 +778,6 @@ export default class CpoOCPIClient extends OCPIClient { `{{inSuccess}} EVSE Status(es) were successfully patched and {{inError}} failed to be patched in ${executionDurationSecs}s`, 'No EVSE Status have been patched' ); - // Return result return result; } @@ -786,30 +785,18 @@ export default class CpoOCPIClient extends OCPIClient { if (!Utils.isEmptyArray(tokens)) { for (const token of tokens) { // Get eMSP user - const email = OCPIUtils.buildEmspEmailFromOCPIToken(token, this.ocpiEndpoint.countryCode, this.ocpiEndpoint.partyId); - // Check cache + const email = OCPIUtils.buildEmspEmailFromOCPIToken( + token, this.ocpiEndpoint.countryCode, this.ocpiEndpoint.partyId); + // Check from cache let emspUser = emspUsers.get(email); if (!emspUser) { - // Get User from DB - emspUser = await UserStorage.getUserByEmail(this.tenant, email); - // Create user - if (!emspUser) { - // Create User - emspUser = { - issuer: false, - createdOn: token.last_updated, - lastChangedOn: token.last_updated, - name: token.issuer, - firstName: OCPIUtils.buildOperatorName(this.ocpiEndpoint.countryCode, this.ocpiEndpoint.partyId), - email: OCPIUtils.buildEmspEmailFromOCPIToken(token, this.ocpiEndpoint.countryCode, this.ocpiEndpoint.partyId), - locale: Utils.getLocaleFromLanguage(token.language), - } as User; - // Save User - emspUser.id = await UserStorage.saveUser(this.tenant, emspUser); - await UserStorage.saveUserRole(this.tenant, emspUser.id, UserRole.BASIC); - await UserStorage.saveUserStatus(this.tenant, emspUser.id, UserStatus.ACTIVE); + // Check eMsp User + emspUser = await OCPIUtils.checkAndCreateEMSPUserFromToken( + this.tenant, this.ocpiEndpoint.countryCode, this.ocpiEndpoint.partyId, token); + if (emspUser) { + // Keep in cache + emspUsers.set(email, emspUser); } - emspUsers.set(email, emspUser); } } } diff --git a/src/client/ocpi/EmspOCPIClient.ts b/src/client/ocpi/EmspOCPIClient.ts index 70edc2f777..caa5441a9e 100644 --- a/src/client/ocpi/EmspOCPIClient.ts +++ b/src/client/ocpi/EmspOCPIClient.ts @@ -409,11 +409,11 @@ export default class EmspOCPIClient extends OCPIClient { module: MODULE_NAME, method: 'remoteStopSession' }); } - if (!transaction.issuer) { + if (transaction.issuer) { throw new BackendError({ ...LoggingHelper.getTransactionProperties(transaction), action: ServerAction.OCPI_EMSP_START_SESSION, - message: `${Utils.buildConnectorInfo(transaction.connectorId, transaction.id)} Transaction belongs to an external organization`, + message: `${Utils.buildConnectorInfo(transaction.connectorId, transaction.id)} Transaction belongs to a local organization`, module: MODULE_NAME, method: 'remoteStopSession', detailedMessages: { transaction } }); diff --git a/src/integration/billing/BillingIntegration.ts b/src/integration/billing/BillingIntegration.ts index 643922ea70..1c313fa221 100644 --- a/src/integration/billing/BillingIntegration.ts +++ b/src/integration/billing/BillingIntegration.ts @@ -324,26 +324,41 @@ export default abstract class BillingIntegration { protected async checkBillingDataThreshold(transaction: Transaction): Promise { // Do not bill suspicious StopTransaction events if (!Utils.isDevelopmentEnv()) { - // Suspicious StopTransaction may occur after a 'Housing temperature approaching limit' error on some charging stations const timeSpent = this.computeTimeSpentInSeconds(transaction); - // TODO - make it part of the pricing or billing settings! - if (timeSpent < 60 /* seconds */ || transaction.stop.totalConsumptionWh < 1000 /* 1kWh */) { + if (timeSpent < Constants.AFIREV_MINIMAL_DURATION_THRESHOLD /* 2 minutes */) { await Logging.logWarning({ ...LoggingHelper.getTransactionProperties(transaction), tenantID: this.tenant.id, user: transaction.userID, action: ServerAction.BILLING_TRANSACTION, module: MODULE_NAME, method: 'stopTransaction', - message: `Transaction data is suspicious - Billing operation has been aborted for Transaction ID '${transaction.id}'`, + message: `Transaction duration is too short - billing operation has been aborted - transaction ID: ${transaction.id}`, + }); + // Abort the billing process - thresholds are not met! + return false; + } + if (transaction.stop.totalConsumptionWh < Constants.AFIREV_MINIMAL_CONSUMPTION_THRESHOLD /* 0.5 kW.h */) { + await Logging.logWarning({ + ...LoggingHelper.getTransactionProperties(transaction), + tenantID: this.tenant.id, + user: transaction.userID, + action: ServerAction.BILLING_TRANSACTION, + module: MODULE_NAME, method: 'stopTransaction', + message: `Transaction consumption is too low - billing operation has been aborted - transaction ID: ${transaction.id}`, }); // Abort the billing process - thresholds are not met! return false; } } - // billing data sounds correct + // Session data seem to be consistent return true; } + protected convertTimeSpentToString(transaction: Transaction): string { + const totalDuration = this.computeTimeSpentInSeconds(transaction); + return moment.duration(totalDuration, 's').format('h[h]mm', { trim: false }); + } + protected computeTimeSpentInSeconds(transaction: Transaction): number { let totalDuration: number; if (!transaction.stop) { @@ -354,11 +369,6 @@ export default abstract class BillingIntegration { return totalDuration; } - protected convertTimeSpentToString(transaction: Transaction): string { - const totalDuration = this.computeTimeSpentInSeconds(transaction); - return moment.duration(totalDuration, 's').format('h[h]mm', { trim: false }); - } - private async _synchronizeUser(user: User, forceMode = false): Promise { // Check if we need to create or update a STRIPE customer let billingUser: BillingUser = null; diff --git a/src/integration/pricing/PricingFacade.ts b/src/integration/pricing/PricingFacade.ts new file mode 100644 index 0000000000..febe5b839e --- /dev/null +++ b/src/integration/pricing/PricingFacade.ts @@ -0,0 +1,79 @@ +import ChargingStation from '../../types/ChargingStation'; +import Consumption from '../../types/Consumption'; +import { PricedConsumption } from '../../types/Pricing'; +import PricingFactory from './PricingFactory'; +import Tenant from '../../types/Tenant'; +import Transaction from '../../types/Transaction'; +import User from '../../types/User'; + +const MODULE_NAME = 'PricingFacade'; + +export default class PricingFacade { + + public static async processStartTransaction(tenant: Tenant, transaction: Transaction, chargingStation: ChargingStation, consumption: Consumption, user: User): Promise { + if (!user?.issuer) { + return; + } + const pricingImpl = await PricingFactory.getPricingImpl(tenant); + if (pricingImpl) { + const pricedConsumption = await pricingImpl.startSession(transaction, consumption, chargingStation); + if (pricedConsumption) { + PricingFacade.updateCumulatedAmounts(transaction, consumption, pricedConsumption); + // Set the initial pricing + transaction.price = pricedConsumption.amount; + transaction.roundedPrice = pricedConsumption.roundedAmount; + transaction.priceUnit = pricedConsumption.currencyCode; + transaction.pricingSource = pricedConsumption.pricingSource; + // Set the actual pricing model after the resolution of the context + transaction.pricingModel = pricedConsumption.pricingModel; + } + } + } + + public static async processUpdateTransaction(tenant: Tenant, transaction: Transaction, chargingStation: ChargingStation, consumption: Consumption, user: User): Promise { + if (!user?.issuer) { + return; + } + const pricingImpl = await PricingFactory.getPricingImpl(tenant); + if (pricingImpl) { + const pricedConsumption = await pricingImpl.updateSession(transaction, consumption, chargingStation); + PricingFacade.updateCumulatedAmounts(transaction, consumption, pricedConsumption); + } + } + + public static async processStopTransaction(tenant: Tenant, transaction: Transaction, chargingStation: ChargingStation, consumption: Consumption, user: User): Promise { + if (!user?.issuer) { + return; + } + const pricingImpl = await PricingFactory.getPricingImpl(tenant); + if (pricingImpl) { + const pricedConsumption = await pricingImpl.stopSession(transaction, consumption, chargingStation); + PricingFacade.updateCumulatedAmounts(transaction, consumption, pricedConsumption); + } + } + + public static async processEndTransaction(tenant: Tenant, transaction: Transaction, chargingStation: ChargingStation, consumption: Consumption, user: User): Promise { + if (!user?.issuer) { + return; + } + const pricingImpl = await PricingFactory.getPricingImpl(tenant); + if (pricingImpl) { + const pricedConsumption = await pricingImpl.endSession(transaction, consumption, chargingStation); + PricingFacade.updateCumulatedAmounts(transaction, consumption, pricedConsumption); + } + } + + private static updateCumulatedAmounts(transaction: Transaction, consumption: Consumption, pricedConsumption: PricedConsumption): void { + if (pricedConsumption) { + // Update consumption + consumption.amount = pricedConsumption.amount; + consumption.roundedAmount = pricedConsumption.roundedAmount; + consumption.currencyCode = pricedConsumption.currencyCode; + consumption.pricingSource = pricedConsumption.pricingSource; + consumption.cumulatedAmount = pricedConsumption.cumulatedAmount; + // Update transaction + transaction.currentCumulatedPrice = consumption.cumulatedAmount; + transaction.currentCumulatedRoundedPrice = pricedConsumption.cumulatedRoundedAmount; + } + } +} diff --git a/src/migration/tasks/AlignEntitiesWithOrganizationIDsTask.ts b/src/migration/tasks/AlignEntitiesWithOrganizationIDsTask.ts index e60bf8e983..55b33f3823 100644 --- a/src/migration/tasks/AlignEntitiesWithOrganizationIDsTask.ts +++ b/src/migration/tasks/AlignEntitiesWithOrganizationIDsTask.ts @@ -51,7 +51,7 @@ export default class AlignEntitiesWithOrganizationIDsTask extends TenantMigratio } public getVersion(): string { - return '1.0'; + return '1.1'; } public getName(): string { diff --git a/src/notification/NotificationHandler.ts b/src/notification/NotificationHandler.ts index de351eab5e..9cc172103d 100644 --- a/src/notification/NotificationHandler.ts +++ b/src/notification/NotificationHandler.ts @@ -193,7 +193,7 @@ export default class NotificationHandler { } } - public static async sendEndOfSession(tenant: Tenant, notificationID: string, user: User, chargingStation: ChargingStation, + public static async sendEndOfTransaction(tenant: Tenant, notificationID: string, user: User, chargingStation: ChargingStation, sourceData: EndOfSessionNotification): Promise { if (tenant.id !== Constants.DEFAULT_TENANT_ID) { // Get the Tenant logo @@ -244,7 +244,7 @@ export default class NotificationHandler { } } - public static async sendEndOfSignedSession(tenant: Tenant, notificationID: string, user: User, chargingStation: ChargingStation, + public static async sendEndOfSignedTransaction(tenant: Tenant, notificationID: string, user: User, chargingStation: ChargingStation, sourceData: EndOfSignedSessionNotification): Promise { if (tenant.id !== Constants.DEFAULT_TENANT_ID) { // Get the Tenant logo @@ -645,7 +645,7 @@ export default class NotificationHandler { } } - public static async sendSessionStarted(tenant: Tenant, notificationID: string, user: User, chargingStation: ChargingStation, + public static async sendTransactionStarted(tenant: Tenant, notificationID: string, user: User, chargingStation: ChargingStation, sourceData: TransactionStartedNotification): Promise { if (tenant.id !== Constants.DEFAULT_TENANT_ID) { // Get the Tenant logo @@ -894,7 +894,7 @@ export default class NotificationHandler { } } - public static async sendPreparingSessionNotStarted(tenant: Tenant, chargingStation: ChargingStation, user: User, sourceData: PreparingSessionNotStartedNotification): Promise { + public static async sendPreparingTransactionNotStarted(tenant: Tenant, chargingStation: ChargingStation, user: User, sourceData: PreparingSessionNotStartedNotification): Promise { if (tenant.id !== Constants.DEFAULT_TENANT_ID) { // Get the Tenant logo if (Utils.isNullOrUndefined(tenant.logo) || tenant.logo === '') { @@ -1276,7 +1276,7 @@ export default class NotificationHandler { } } - public static async sendSessionNotStarted(tenant: Tenant, notificationID: string, chargingStation: ChargingStation, + public static async sendTransactionNotStarted(tenant: Tenant, notificationID: string, chargingStation: ChargingStation, sourceData: SessionNotStartedNotification): Promise { if (tenant.id !== Constants.DEFAULT_TENANT_ID) { // Get the Tenant logo diff --git a/src/notification/remote-push-notification/RemotePushNotificationTask.ts b/src/notification/remote-push-notification/RemotePushNotificationTask.ts index ac0d53540e..8239f8167c 100644 --- a/src/notification/remote-push-notification/RemotePushNotificationTask.ts +++ b/src/notification/remote-push-notification/RemotePushNotificationTask.ts @@ -29,8 +29,7 @@ export default class RemotePushNotificationTask implements NotificationTask { projectId: this.firebaseConfig.projectID, clientEmail: this.firebaseConfig.clientEmail, privateKey: this.firebaseConfig.privateKey - }), - databaseURL: this.firebaseConfig.databaseURL + }) }); // Init tenant conf if (!Utils.isEmptyArray(this.firebaseConfig.tenants)) { @@ -41,8 +40,7 @@ export default class RemotePushNotificationTask implements NotificationTask { projectId: tenantConfig.configuration.projectID, clientEmail: tenantConfig.configuration.clientEmail, privateKey: tenantConfig.configuration.privateKey - }), - databaseURL: tenantConfig.configuration.databaseURL + }) }, tenantConfig.tenantID); // Keep it per Tenant this.tenantFirebaseApps.set(tenantConfig.tenantID, app); diff --git a/src/scheduler/tasks/CheckPreparingSessionNotStartedTask.ts b/src/scheduler/tasks/CheckPreparingSessionNotStartedTask.ts index 6e54745ce4..c4b400da8d 100644 --- a/src/scheduler/tasks/CheckPreparingSessionNotStartedTask.ts +++ b/src/scheduler/tasks/CheckPreparingSessionNotStartedTask.ts @@ -35,7 +35,7 @@ export default class CheckPreparingSessionNotStartedTask extends TenantScheduler // Send notification moment.locale(siteOwners.result[0].user.locale); for (const connector of chargingStation.connectors) { - void NotificationHandler.sendPreparingSessionNotStarted(tenant, chargingStation, siteOwners.result[0].user, { + void NotificationHandler.sendPreparingTransactionNotStarted(tenant, chargingStation, siteOwners.result[0].user, { user: siteOwners.result[0].user, chargeBoxID: chargingStation.id, siteID: chargingStation.siteID, diff --git a/src/scheduler/tasks/CheckSessionNotStartedAfterAuthorizeTask.ts b/src/scheduler/tasks/CheckSessionNotStartedAfterAuthorizeTask.ts index ef935a303b..267a1472bf 100644 --- a/src/scheduler/tasks/CheckSessionNotStartedAfterAuthorizeTask.ts +++ b/src/scheduler/tasks/CheckSessionNotStartedAfterAuthorizeTask.ts @@ -22,7 +22,7 @@ export default class CheckSessionNotStartedAfterAuthorizeTask extends TenantSche }); if (notificationTransactionNotStarted.result && notificationTransactionNotStarted.result.length > 0) { for (const notification of notificationTransactionNotStarted.result) { - void NotificationHandler.sendSessionNotStarted(tenant, + void NotificationHandler.sendTransactionNotStarted(tenant, `${notification.tagID}-${notification.authDate.toString()}`, notification.chargingStation, { user: notification.user, diff --git a/src/scheduler/tasks/LoggingDatabaseTableCleanupTask.ts b/src/scheduler/tasks/LoggingDatabaseTableCleanupTask.ts index 52090b247a..e7ff9f13c5 100644 --- a/src/scheduler/tasks/LoggingDatabaseTableCleanupTask.ts +++ b/src/scheduler/tasks/LoggingDatabaseTableCleanupTask.ts @@ -4,7 +4,7 @@ import Constants from '../../utils/Constants'; import { LockEntity } from '../../types/Locking'; import LockingManager from '../../locking/LockingManager'; import Logging from '../../utils/Logging'; -import LoggingStorage from '../../storage/mongodb/LoggingStorage'; +import LogStorage from '../../storage/mongodb/LogStorage'; import PerformanceStorage from '../../storage/mongodb/PerformanceStorage'; import { ServerAction } from '../../types/Server'; import Tenant from '../../types/Tenant'; @@ -29,7 +29,7 @@ export default class LoggingDatabaseTableCleanupTask extends TenantSchedulerTask private async deleteLogs(tenant: Tenant, config: LoggingDatabaseTableCleanupTaskConfig) { // Get the lock - const logsCleanUpLock = LockingManager.createExclusiveLock(tenant.id, LockEntity.LOGGING, 'cleanup'); + const logsCleanUpLock = LockingManager.createExclusiveLock(tenant.id, LockEntity.LOG, 'cleanup'); if (await LockingManager.acquire(logsCleanUpLock)) { try { const lastLogMDB = global.database.getCollection(tenant.id, 'logs').find({}) @@ -45,7 +45,7 @@ export default class LoggingDatabaseTableCleanupTask extends TenantSchedulerTask deleteUpToDate = moment().subtract(config.retentionPeriodWeeks, 'w').toDate(); } // Delete - const result = await LoggingStorage.deleteLogs(tenant, deleteUpToDate); + const result = await LogStorage.deleteLogs(tenant, deleteUpToDate); if (result.acknowledged) { await Logging.logInfo({ tenantID: tenant.id, diff --git a/src/server/ocpi/OCPIUtils.ts b/src/server/ocpi/OCPIUtils.ts index 22a2899ee0..79c60150c5 100644 --- a/src/server/ocpi/OCPIUtils.ts +++ b/src/server/ocpi/OCPIUtils.ts @@ -4,6 +4,7 @@ import OCPIEndpoint, { OCPIAvailableEndpoints, OCPIEndpointVersions } from '../. import { OCPIEvse, OCPIEvseStatus } from '../../types/ocpi/OCPIEvse'; import { OCPITariff, OCPITariffDimensionType } from '../../types/ocpi/OCPITariff'; import { OCPIToken, OCPITokenType, OCPITokenWhitelist } from '../../types/ocpi/OCPIToken'; +import User, { UserRole, UserStatus } from '../../types/User'; import AppError from '../../exception/AppError'; import BackendError from '../../exception/BackendError'; @@ -32,7 +33,7 @@ import SiteAreaStorage from '../../storage/mongodb/SiteAreaStorage'; import SiteStorage from '../../storage/mongodb/SiteStorage'; import Tag from '../../types/Tag'; import Tenant from '../../types/Tenant'; -import { UserStatus } from '../../types/User'; +import UserStorage from '../../storage/mongodb/UserStorage'; import Utils from '../../utils/Utils'; import moment from 'moment'; @@ -145,9 +146,32 @@ export default class OCPIUtils { } public static buildEmspEmailFromOCPIToken(token: OCPIToken, countryCode: string, partyId: string): string { - if (token?.issuer) { - return `${token.issuer}@${partyId}.${countryCode}`.toLowerCase(); + return `${token.issuer}@${partyId}.${countryCode}`.toLowerCase(); + } + + public static async checkAndCreateEMSPUserFromToken(tenant: Tenant, countryCode: string, partyId: string, token: OCPIToken): Promise { + // Get eMSP user + const email = OCPIUtils.buildEmspEmailFromOCPIToken(token, countryCode, partyId); + // Get User from DB + let emspUser = await UserStorage.getUserByEmail(tenant, email); + // Create user + if (!emspUser) { + // Create User + emspUser = { + issuer: false, + createdOn: token.last_updated, + lastChangedOn: token.last_updated, + name: token.issuer, + firstName: OCPIUtils.buildOperatorName(countryCode, partyId), + email, + locale: Utils.getLocaleFromLanguage(token.language), + } as User; + // Save User + emspUser.id = await UserStorage.saveUser(tenant, emspUser); + await UserStorage.saveUserRole(tenant, emspUser.id, UserRole.BASIC); + await UserStorage.saveUserStatus(tenant, emspUser.id, UserStatus.ACTIVE); } + return emspUser; } public static atob(base64: string): string { @@ -407,10 +431,10 @@ export default class OCPIUtils { public static convertStatus2OCPIStatus(status: ChargePointStatus): OCPIEvseStatus { switch (status) { + case ChargePointStatus.PREPARING: case ChargePointStatus.AVAILABLE: return OCPIEvseStatus.AVAILABLE; case ChargePointStatus.OCCUPIED: - case ChargePointStatus.PREPARING: case ChargePointStatus.SUSPENDED_EV: case ChargePointStatus.SUSPENDED_EVSE: case ChargePointStatus.FINISHING: diff --git a/src/server/ocpi/router/cpo/V2.1.1/CPOCdrsRouterV211.ts b/src/server/ocpi/router/cpo/V2.1.1/CPOCdrsRouterV211.ts index f059eae6f2..a5b5cc2994 100644 --- a/src/server/ocpi/router/cpo/V2.1.1/CPOCdrsRouterV211.ts +++ b/src/server/ocpi/router/cpo/V2.1.1/CPOCdrsRouterV211.ts @@ -1,5 +1,4 @@ import { OCPIServerRoute, ServerAction } from '../../../../../types/Server'; -/* eslint-disable @typescript-eslint/no-misused-promises */ import express, { NextFunction, Request, Response } from 'express'; import CPOCdrsService from '../../../service/cpo/v2.1.1/CPOCdrsService'; @@ -18,8 +17,8 @@ export default class CPOCdrsRouterV211 { } protected buildRouteGetCdrs(): void { - this.router.get(`/${OCPIServerRoute.OCPI_CDRS}*`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleOCPIServerAction(CPOCdrsService.handleGetCdrs.bind(this), ServerAction.OCPI_CPO_GET_CDRS, req, res, next); + this.router.get(`/${OCPIServerRoute.OCPI_CDRS}*`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleOCPIServerAction(CPOCdrsService.handleGetCdrs.bind(this), ServerAction.OCPI_CPO_GET_CDRS, req, res, next); }); } } diff --git a/src/server/ocpi/service/OCPIUtilsService.ts b/src/server/ocpi/service/OCPIUtilsService.ts index 4774ba371a..3ec05a08be 100644 --- a/src/server/ocpi/service/OCPIUtilsService.ts +++ b/src/server/ocpi/service/OCPIUtilsService.ts @@ -561,7 +561,7 @@ export default class OCPIUtilsService { await OCPPUtils.updateChargingStationConnectorRuntimeDataWithTransaction(tenant, chargingStation, transaction, true); } - public static async updateCpoToken(tenant: Tenant, token: OCPIToken, tag: Tag, emspUser: User, action: ServerAction): Promise { + public static async updateCreateTagWithCpoToken(tenant: Tenant, token: OCPIToken, tag: Tag, emspUser: User, action: ServerAction): Promise { if (!OCPIUtilsService.validateCpoToken(token)) { throw new AppError({ module: MODULE_NAME, method: 'updateCpoToken', action, @@ -610,12 +610,14 @@ export default class OCPIUtilsService { active: token.valid === true ? true : false, description: token.visual_number, lastChangedOn: token.last_updated, - ocpiToken: token + ocpiToken: token, + user: emspUser, }; // Save Tag if (!tag || JSON.stringify(tagToSave.ocpiToken) !== JSON.stringify(tag.ocpiToken)) { await TagStorage.saveTag(tenant, tagToSave); } + return tagToSave; } public static convertConnector2OcpiConnector(tenant: Tenant, chargingStation: ChargingStation, diff --git a/src/server/ocpi/service/cpo/v2.1.1/CPOCommandsService.ts b/src/server/ocpi/service/cpo/v2.1.1/CPOCommandsService.ts index 695ff7fb4a..22fdf8d156 100644 --- a/src/server/ocpi/service/cpo/v2.1.1/CPOCommandsService.ts +++ b/src/server/ocpi/service/cpo/v2.1.1/CPOCommandsService.ts @@ -1,4 +1,4 @@ -import ChargingStation, { Connector, RemoteAuthorization } from '../../../../../types/ChargingStation'; +import ChargingStation, { Connector } from '../../../../../types/ChargingStation'; import { NextFunction, Request, Response } from 'express'; import { OCPICommandResponse, OCPICommandResponseType } from '../../../../../types/ocpi/OCPICommandResponse'; @@ -70,7 +70,8 @@ export default class CPOCommandsService { next(); } - private static async remoteStartSession(action: ServerAction, req: Request, res: Response, next: NextFunction, tenant: Tenant, ocpiEndpoint: OCPIEndpoint): Promise { + private static async remoteStartSession(action: ServerAction, req: Request, res: Response, + next: NextFunction, tenant: Tenant, ocpiEndpoint: OCPIEndpoint): Promise { const startSession = req.body as OCPIStartSession; if (!CPOCommandsService.validateStartSession(startSession)) { throw new AppError({ @@ -81,8 +82,15 @@ export default class CPOCommandsService { ocpiError: OCPIStatusCode.CODE_2001_INVALID_PARAMETER_ERROR }); } - const localToken = await TagStorage.getTag( + let localToken = await TagStorage.getTag( tenant, startSession.token.uid, { withUser: true }); + // Create it on the fly + if (!localToken) { + // Check eMSP user + const emspUser = await OCPIUtils.checkAndCreateEMSPUserFromToken( + tenant, ocpiEndpoint.countryCode, ocpiEndpoint.partyId, startSession.token); + localToken = await OCPIUtilsService.updateCreateTagWithCpoToken(tenant, startSession.token, localToken, emspUser, action); + } if (!localToken?.active || !localToken.ocpiToken?.valid) { await Logging.logError({ tenantID: tenant.id, @@ -267,47 +275,67 @@ export default class CPOCommandsService { private static async remoteStartTransaction(action: ServerAction, tenant: Tenant, chargingStation: ChargingStation, connector: Connector, startSession: OCPIStartSession, ocpiEndpoint: OCPIEndpoint): Promise { - const chargingStationClient = await ChargingStationClientFactory.getChargingStationClient(tenant, chargingStation); - if (!chargingStationClient) { + try { + const chargingStationClient = await ChargingStationClientFactory.getChargingStationClient(tenant, chargingStation); + if (!chargingStationClient) { + await Logging.logError({ + ...LoggingHelper.getChargingStationProperties(chargingStation), + tenantID: tenant.id, + module: MODULE_NAME, method: 'remoteStartTransaction', action, + message: 'Charging Station is not connected to the backend', + detailedMessages: { startSession, chargingStation }, + }); + } + const result = await chargingStationClient.remoteStartTransaction({ + connectorId: connector.connectorId, + idTag: startSession.token.uid + }); + if (result?.status === OCPPRemoteStartStopStatus.ACCEPTED) { + await CPOCommandsService.sendCommandResponse(tenant, action, startSession.response_url, OCPICommandResponseType.ACCEPTED, ocpiEndpoint); + } else { + await CPOCommandsService.sendCommandResponse(tenant, action, startSession.response_url, OCPICommandResponseType.REJECTED, ocpiEndpoint); + } + } catch (error) { await Logging.logError({ ...LoggingHelper.getChargingStationProperties(chargingStation), tenantID: tenant.id, module: MODULE_NAME, method: 'remoteStartTransaction', action, - message: 'Charging Station is not connected to the backend', + message: `Error while trying to Start a Transaction remotely: ${error.message as string}`, detailedMessages: { startSession, chargingStation }, }); - } - const result = await chargingStationClient.remoteStartTransaction({ - connectorId: connector.connectorId, - idTag: startSession.token.uid - }); - if (result?.status === OCPPRemoteStartStopStatus.ACCEPTED) { - await CPOCommandsService.sendCommandResponse(tenant, action, startSession.response_url, OCPICommandResponseType.ACCEPTED, ocpiEndpoint); - } else { - await CPOCommandsService.sendCommandResponse(tenant, action, startSession.response_url, OCPICommandResponseType.REJECTED, ocpiEndpoint); - } + } } private static async remoteStopTransaction(action: ServerAction, tenant: Tenant, chargingStation: ChargingStation, transactionId: number, stopSession: OCPIStopSession, ocpiEndpoint: OCPIEndpoint): Promise { - const chargingStationClient = await ChargingStationClientFactory.getChargingStationClient(tenant, chargingStation); - if (!chargingStationClient) { + try { + const chargingStationClient = await ChargingStationClientFactory.getChargingStationClient(tenant, chargingStation); + if (!chargingStationClient) { + await Logging.logError({ + ...LoggingHelper.getChargingStationProperties(chargingStation), + tenantID: tenant.id, + module: MODULE_NAME, method: 'remoteStopTransaction', action, + message: 'Charging Station is not connected to the backend', + detailedMessages: { transactionId, stopSession, chargingStation }, + }); + } + const result = await chargingStationClient.remoteStopTransaction({ + transactionId: transactionId + }); + if (result?.status === OCPPRemoteStartStopStatus.ACCEPTED) { + await CPOCommandsService.sendCommandResponse(tenant, action, stopSession.response_url, OCPICommandResponseType.ACCEPTED, ocpiEndpoint); + } else { + await CPOCommandsService.sendCommandResponse(tenant, action, stopSession.response_url, OCPICommandResponseType.REJECTED, ocpiEndpoint); + } + } catch (error) { await Logging.logError({ ...LoggingHelper.getChargingStationProperties(chargingStation), tenantID: tenant.id, module: MODULE_NAME, method: 'remoteStopTransaction', action, - message: 'Charging Station is not connected to the backend', + message: `Error while trying to Stop a Transaction remotely: ${error.message as string}`, detailedMessages: { transactionId, stopSession, chargingStation }, }); } - const result = await chargingStationClient.remoteStopTransaction({ - transactionId: transactionId - }); - if (result?.status === OCPPRemoteStartStopStatus.ACCEPTED) { - await CPOCommandsService.sendCommandResponse(tenant, action, stopSession.response_url, OCPICommandResponseType.ACCEPTED, ocpiEndpoint); - } else { - await CPOCommandsService.sendCommandResponse(tenant, action, stopSession.response_url, OCPICommandResponseType.REJECTED, ocpiEndpoint); - } } private static async sendCommandResponse(tenant: Tenant, action: ServerAction, responseUrl: string, responseType: OCPICommandResponseType, ocpiEndpoint: OCPIEndpoint) { diff --git a/src/server/ocpi/service/cpo/v2.1.1/CPOTokensService.ts b/src/server/ocpi/service/cpo/v2.1.1/CPOTokensService.ts index f94df8bfc6..ee9c5f333e 100644 --- a/src/server/ocpi/service/cpo/v2.1.1/CPOTokensService.ts +++ b/src/server/ocpi/service/cpo/v2.1.1/CPOTokensService.ts @@ -109,7 +109,7 @@ export default class CPOTokensService { detailedMessages: { operator, token, tag } }); } - await OCPIUtilsService.updateCpoToken(tenant, token, tag, tag.user, ServerAction.OCPI_CPO_UPDATE_TOKEN); + await OCPIUtilsService.updateCreateTagWithCpoToken(tenant, token, tag, tag.user, ServerAction.OCPI_CPO_UPDATE_TOKEN); res.json(OCPIUtils.success()); next(); } diff --git a/src/server/ocpp/json/web-socket/JsonWSConnection.ts b/src/server/ocpp/json/web-socket/JsonWSConnection.ts index 49176cdff8..56289f5030 100644 --- a/src/server/ocpp/json/web-socket/JsonWSConnection.ts +++ b/src/server/ocpp/json/web-socket/JsonWSConnection.ts @@ -70,7 +70,7 @@ export default class JsonWSConnection extends WSConnection { if (typeof this.chargingStationService[methodName] === 'function') { this.headers.currentIPAddress = this.getClientIP(); // Check the Charging Station - const { tenant, chargingStation, token } = await OCPPUtils.checkAndGetChargingStationData(OCPPUtils.buildServerActionFromOcppCommand(command), + const { tenant, chargingStation, token } = await OCPPUtils.checkAndGetChargingStationConnectionData(OCPPUtils.buildServerActionFromOcppCommand(command), this.getTenantID(), this.getChargingStationID(), this.getTokenID()); // Set the header this.headers.tenant = tenant; diff --git a/src/server/ocpp/json/web-socket/WSConnection.ts b/src/server/ocpp/json/web-socket/WSConnection.ts index 3cecdbc531..1ee1992c5e 100644 --- a/src/server/ocpp/json/web-socket/WSConnection.ts +++ b/src/server/ocpp/json/web-socket/WSConnection.ts @@ -38,7 +38,7 @@ export default abstract class WSConnection { public async initialize(): Promise { // Check and Get Charging Station data - const { tenant, chargingStation } = await OCPPUtils.checkAndGetChargingStationData( + const { tenant, chargingStation } = await OCPPUtils.checkAndGetChargingStationConnectionData( ServerAction.WS_SERVER_CONNECTION, this.getTenantID(), this.getChargingStationID(), this.getTokenID()); // Set this.setTenant(tenant); @@ -332,7 +332,7 @@ export default abstract class WSConnection { this.tokenID = splittedURL[2]; this.chargingStationID = splittedURL[3]; // Check parameters - OCPPUtils.checkChargingStationOcppParameters( + OCPPUtils.checkChargingStationConnectionData( ServerAction.WS_SERVER_CONNECTION, this.tenantID, this.tokenID, this.chargingStationID); } diff --git a/src/server/ocpp/services/OCPPService.ts b/src/server/ocpp/services/OCPPService.ts index 5c0c4196d7..1a77c86823 100644 --- a/src/server/ocpp/services/OCPPService.ts +++ b/src/server/ocpp/services/OCPPService.ts @@ -30,6 +30,7 @@ import OCPPStorage from '../../../storage/mongodb/OCPPStorage'; import OCPPUtils from '../utils/OCPPUtils'; import OCPPValidation from '../validation/OCPPValidation'; import OICPFacade from '../../oicp/OICPFacade'; +import PricingFacade from '../../../integration/pricing/PricingFacade'; import { ServerAction } from '../../../types/Server'; import SiteArea from '../../../types/SiteArea'; import SiteAreaStorage from '../../../storage/mongodb/SiteAreaStorage'; @@ -114,13 +115,14 @@ export default class OCPPService { try { // Get the header infos const { chargingStation, tenant } = headers; + if (!heartbeat) { + heartbeat = {} as OCPPHeartbeatRequestExtended; + } OCPPValidation.getInstance().validateHeartbeat(heartbeat); // Set Heart Beat Object - heartbeat = { - chargeBoxID: chargingStation.id, - timestamp: new Date(), - timezone: Utils.getTimezone(chargingStation.coordinates) - }; + heartbeat.chargeBoxID = chargingStation.id; + heartbeat.timestamp = new Date(); + heartbeat.timezone = Utils.getTimezone(chargingStation.coordinates); // Save Heart Beat await OCPPStorage.saveHeartbeat(tenant, heartbeat); await Logging.logInfo({ @@ -209,7 +211,7 @@ export default class OCPPService { OCPPUtils.updateTransactionWithConsumption(chargingStation, transaction, consumption); if (consumption.toPrice) { // Pricing - await OCPPUtils.processTransactionPricing(tenant, transaction, chargingStation, consumption, TransactionAction.UPDATE); + await PricingFacade.processUpdateTransaction(tenant, transaction, chargingStation, consumption, transaction.user); // Billing await BillingFacade.processUpdateTransaction(tenant, transaction, transaction.user); } @@ -377,7 +379,7 @@ export default class OCPPService { // Create consumption const firstConsumption = await OCPPUtils.createFirstConsumption(tenant, chargingStation, newTransaction); // Pricing - await OCPPUtils.processTransactionPricing(tenant, newTransaction, chargingStation, firstConsumption, TransactionAction.START); + await PricingFacade.processStartTransaction(tenant, newTransaction, chargingStation, firstConsumption, user); // Billing await BillingFacade.processStartTransaction(tenant, newTransaction, chargingStation, chargingStation.siteArea, user); // OCPI @@ -482,7 +484,7 @@ export default class OCPPService { // Soft Stop this.checkSoftStopTransaction(transaction, stopTransaction, isSoftStop); // Transaction End has already been received? - await this.checkAndApplyLastConsumptionInStopTransaction(tenant, chargingStation, transaction, stopTransaction); + await this.checkAndApplyLastConsumptionInStopTransaction(tenant, chargingStation, transaction, stopTransaction, user); // Signed Data this.checkAndUpdateTransactionWithSignedDataInStopTransaction(transaction, stopTransaction); // Update Transaction with Stop Transaction and Stop MeterValues @@ -801,7 +803,7 @@ export default class OCPPService { if (lastTransaction.stop) { // Check Inactivity const transactionUpdated = await this.checkAndComputeTransactionExtraInactivityFromStatusNotification( - tenant, chargingStation, lastTransaction, connector, statusNotification); + tenant, chargingStation, lastTransaction, lastTransaction.user, connector, statusNotification); // Billing: Trigger the asynchronous billing task const billingDataUpdated = await this.checkAndBillTransaction(tenant, lastTransaction); // OCPI: Post the CDR @@ -831,7 +833,7 @@ export default class OCPPService { } private async checkAndComputeTransactionExtraInactivityFromStatusNotification(tenant: Tenant, chargingStation: ChargingStation, - transaction: Transaction, connector: Connector, statusNotification: OCPPStatusNotificationRequestExtended): Promise { + transaction: Transaction, user: User, connector: Connector, statusNotification: OCPPStatusNotificationRequestExtended): Promise { let extraInactivityUpdated = false; if (Utils.objectHasProperty(statusNotification, 'timestamp')) { // Session is finished @@ -855,7 +857,7 @@ export default class OCPPService { await Logging.logWarning({ ...LoggingHelper.getChargingStationProperties(chargingStation), tenantID: tenant.id, - module: MODULE_NAME, method: 'checkAndUpdateLastCompletedTransaction', + module: MODULE_NAME, method: 'checkAndComputeTransactionExtraInactivityFromStatusNotification', action: ServerAction.OCPP_STATUS_NOTIFICATION, message: `${Utils.buildConnectorInfo(transaction.connectorId, transaction.id)} Extra Inactivity is negative and will be ignored: ${transaction.stop.extraInactivitySecs} secs`, detailedMessages: { statusNotification } @@ -869,12 +871,12 @@ export default class OCPPService { transaction.stop.totalInactivitySecs + transaction.stop.extraInactivitySecs ); // Build extra inactivity consumption - await OCPPUtils.buildAndPriceExtraConsumptionInactivity(tenant, chargingStation, transaction); + await OCPPUtils.buildAndPriceExtraConsumptionInactivity(tenant, user, chargingStation, transaction); await Logging.logInfo({ ...LoggingHelper.getChargingStationProperties(chargingStation), tenantID: tenant.id, user: transaction.userID, - module: MODULE_NAME, method: 'checkAndUpdateLastCompletedTransaction', + module: MODULE_NAME, method: 'checkAndComputeTransactionExtraInactivityFromStatusNotification', action: ServerAction.EXTRA_INACTIVITY, message: `${Utils.buildConnectorInfo(transaction.connectorId, transaction.id)} Extra Inactivity of ${transaction.stop.extraInactivitySecs} secs has been added`, detailedMessages: { statusNotification, connector, lastTransaction: transaction } @@ -886,7 +888,7 @@ export default class OCPPService { ...LoggingHelper.getChargingStationProperties(chargingStation), tenantID: tenant.id, user: transaction.userID, - module: MODULE_NAME, method: 'checkAndUpdateLastCompletedTransaction', + module: MODULE_NAME, method: 'checkAndComputeTransactionExtraInactivityFromStatusNotification', action: ServerAction.EXTRA_INACTIVITY, message: `${Utils.buildConnectorInfo(transaction.connectorId, transaction.id)} No Extra Inactivity for this transaction`, detailedMessages: { statusNotification, connector, lastTransaction: transaction } @@ -1799,7 +1801,7 @@ export default class OCPPService { } private async checkAndApplyLastConsumptionInStopTransaction(tenant: Tenant, chargingStation: ChargingStation, - transaction: Transaction, stopTransaction: OCPPStopTransactionRequestExtended) { + transaction: Transaction, stopTransaction: OCPPStopTransactionRequestExtended, user: User) { // No need to compute the last consumption if Transaction.End Meter Value has been received if (!transaction.transactionEndReceived) { // Recreate the last meter value to price the last Consumption @@ -1812,7 +1814,7 @@ export default class OCPPService { OCPPUtils.updateTransactionWithConsumption(chargingStation, transaction, consumption); if (consumption.toPrice) { // Price - await OCPPUtils.processTransactionPricing(tenant, transaction, chargingStation, consumption, TransactionAction.STOP); + await PricingFacade.processStopTransaction(tenant, transaction, chargingStation, consumption, user); } // Save Consumption await ConsumptionStorage.saveConsumption(tenant, consumption); @@ -1825,6 +1827,7 @@ export default class OCPPService { ...LoggingHelper.getChargingStationProperties(chargingStation), tenantID: tenant.id, action: ServerAction.OCPP_STOP_TRANSACTION, + actionOnUser: user, module: MODULE_NAME, method: 'checkAndApplyLastConsumptionInStopTransaction', message: `${Utils.buildConnectorInfo(transaction.connectorId, transaction.id)} Transaction.End consumption '${transaction.lastConsumption.value}' differs from Stop Transaction '${stopTransaction.meterStop}'`, detailedMessages: { stopTransaction, transaction } diff --git a/src/server/ocpp/utils/OCPPUtils.ts b/src/server/ocpp/utils/OCPPUtils.ts index 2770dedf28..60d99e80da 100644 --- a/src/server/ocpp/utils/OCPPUtils.ts +++ b/src/server/ocpp/utils/OCPPUtils.ts @@ -3,7 +3,7 @@ import ChargingStation, { ChargingStationCapabilities, ChargingStationTemplate, import { OCPPChangeConfigurationResponse, OCPPChargingProfileStatus, OCPPConfigurationStatus } from '../../../types/ocpp/OCPPClient'; import { OCPPMeasurand, OCPPNormalizedMeterValue, OCPPPhase, OCPPReadingContext, OCPPStopTransactionRequestExtended, OCPPUnitOfMeasure, OCPPValueFormat } from '../../../types/ocpp/OCPPServer'; import Tenant, { TenantComponents } from '../../../types/Tenant'; -import Transaction, { InactivityStatus, TransactionAction } from '../../../types/Transaction'; +import Transaction, { InactivityStatus } from '../../../types/Transaction'; import { ActionsResponse } from '../../../types/GlobalType'; import BackendError from '../../../exception/BackendError'; @@ -18,8 +18,7 @@ import Logging from '../../../utils/Logging'; import LoggingHelper from '../../../utils/LoggingHelper'; import OCPPCommon from './OCPPCommon'; import { OCPPHeader } from '../../../types/ocpp/OCPPHeader'; -import { PricedConsumption } from '../../../types/Pricing'; -import PricingFactory from '../../../integration/pricing/PricingFactory'; +import PricingFacade from '../../../integration/pricing/PricingFacade'; import { PricingSettingsType } from '../../../types/Setting'; import { Promise } from 'bluebird'; import RegistrationToken from '../../../types/RegistrationToken'; @@ -88,12 +87,12 @@ export default class OCPPUtils { return token; } - public static async buildAndPriceExtraConsumptionInactivity(tenant: Tenant, chargingStation: ChargingStation, lastTransaction: Transaction): Promise { + public static async buildAndPriceExtraConsumptionInactivity(tenant: Tenant, user: User, chargingStation: ChargingStation, lastTransaction: Transaction): Promise { const lastConsumption = await OCPPUtils.buildExtraConsumptionInactivity(tenant, lastTransaction); if (lastConsumption) { // Pricing of the extra inactivity if (lastConsumption?.toPrice) { - await OCPPUtils.processTransactionPricing(tenant, lastTransaction, chargingStation, lastConsumption, TransactionAction.END); + await PricingFacade.processEndTransaction(tenant, lastTransaction, chargingStation, lastConsumption, user); } // Save the last consumption await ConsumptionStorage.saveConsumption(tenant, lastConsumption); @@ -139,60 +138,6 @@ export default class OCPPUtils { return null; } - public static async processTransactionPricing(tenant: Tenant, transaction: Transaction, chargingStation: ChargingStation, - consumption: Consumption, action: TransactionAction): Promise { - let pricedConsumption: PricedConsumption; - // Get the pricing impl - const pricingImpl = await PricingFactory.getPricingImpl(tenant); - if (pricingImpl) { - switch (action) { - // Start Transaction - case TransactionAction.START: - pricedConsumption = await pricingImpl.startSession(transaction, consumption, chargingStation); - if (pricedConsumption) { - OCPPUtils.updateCumulatedAmounts(transaction, consumption, pricedConsumption); - // Set the initial pricing - transaction.price = pricedConsumption.amount; - transaction.roundedPrice = pricedConsumption.roundedAmount; - transaction.priceUnit = pricedConsumption.currencyCode; - transaction.pricingSource = pricedConsumption.pricingSource; - // Set the actual pricing model after the resolution of the context - transaction.pricingModel = pricedConsumption.pricingModel; - } - break; - case TransactionAction.UPDATE: - // Set - pricedConsumption = await pricingImpl.updateSession(transaction, consumption, chargingStation); - OCPPUtils.updateCumulatedAmounts(transaction, consumption, pricedConsumption); - break; - case TransactionAction.STOP: - // Set - pricedConsumption = await pricingImpl.stopSession(transaction, consumption, chargingStation); - OCPPUtils.updateCumulatedAmounts(transaction, consumption, pricedConsumption); - break; - case TransactionAction.END: - // Set - pricedConsumption = await pricingImpl.endSession(transaction, consumption, chargingStation); - OCPPUtils.updateCumulatedAmounts(transaction, consumption, pricedConsumption); - break; - } - } - } - - public static updateCumulatedAmounts(transaction: Transaction, consumption: Consumption, pricedConsumption: PricedConsumption): void { - if (pricedConsumption) { - // Update consumption - consumption.amount = pricedConsumption.amount; - consumption.roundedAmount = pricedConsumption.roundedAmount; - consumption.currencyCode = pricedConsumption.currencyCode; - consumption.pricingSource = pricedConsumption.pricingSource; - consumption.cumulatedAmount = pricedConsumption.cumulatedAmount; - // Update transaction - transaction.currentCumulatedPrice = consumption.cumulatedAmount; - transaction.currentCumulatedRoundedPrice = pricedConsumption.cumulatedRoundedAmount; - } - } - public static assertConsistencyInConsumption(chargingStation: ChargingStation, connectorID: number, consumption: Consumption): void { // Check Total Power with Meter Value Power L1, L2, L3 if (consumption.instantWattsL1 > 0 || consumption.instantWattsL2 > 0 || consumption.instantWattsL3 > 0) { @@ -1129,7 +1074,7 @@ export default class OCPPUtils { headers.tenantID = urlParts.query.tenantid as string; headers.tokenID = urlParts.query.token as string; // Get all the necessary entities - const { tenant, chargingStation, token } = await OCPPUtils.checkAndGetChargingStationData( + const { tenant, chargingStation, token } = await OCPPUtils.checkAndGetChargingStationConnectionData( OCPPUtils.buildServerActionFromOcppCommand(command), headers.tenantID, headers.chargeBoxIdentity, headers.tokenID); // Set headers.tenant = tenant; @@ -1242,7 +1187,7 @@ export default class OCPPUtils { meterValue.attribute.context === OCPPReadingContext.SAMPLE_PERIODIC); } - public static checkChargingStationOcppParameters(action: ServerAction, tenantID: string, tokenID: string, chargingStationID: string): void { + public static checkChargingStationConnectionData(action: ServerAction, tenantID: string, tokenID: string, chargingStationID: string): void { // Check Charging Station if (!chargingStationID) { throw new BackendError({ @@ -1283,10 +1228,10 @@ export default class OCPPUtils { } } - public static async checkAndGetChargingStationData(action: ServerAction, tenantID: string, chargingStationID: string, + public static async checkAndGetChargingStationConnectionData(action: ServerAction, tenantID: string, chargingStationID: string, tokenID: string): Promise<{ tenant: Tenant; chargingStation?: ChargingStation; token?: RegistrationToken }> { // Check parameters - OCPPUtils.checkChargingStationOcppParameters( + OCPPUtils.checkChargingStationConnectionData( ServerAction.WS_SERVER_CONNECTION, tenantID, tokenID, chargingStationID); // Get Tenant const tenant = await TenantStorage.getTenant(tenantID); @@ -1814,15 +1759,14 @@ export default class OCPPUtils { private static checkAndGetConnectorAmperageLimit(chargingStation: ChargingStation, connector: Connector, nrOfPhases?: number): number { const numberOfPhases = nrOfPhases ?? Utils.getNumberOfConnectedPhases(chargingStation, null, connector.connectorId); - const connectorAmperageLimitMax = Utils.getChargingStationAmperage(chargingStation, null, connector.connectorId); const connectorAmperageLimitMin = StaticLimitAmps.MIN_LIMIT_PER_PHASE * numberOfPhases; - if (!Utils.objectHasProperty(connector, 'amperageLimit') || (Utils.objectHasProperty(connector, 'amperageLimit') && Utils.isNullOrUndefined(connector.amperageLimit))) { - return connectorAmperageLimitMax; - } else if (Utils.objectHasProperty(connector, 'amperageLimit') && connector.amperageLimit > connectorAmperageLimitMax) { - return connectorAmperageLimitMax; - } else if (Utils.objectHasProperty(connector, 'amperageLimit') && connector.amperageLimit < connectorAmperageLimitMin) { + if (connector.amperageLimit // Must be ignored when set to 0 + && connector.amperageLimit < connectorAmperageLimitMin) { + // Return the minimal value return connectorAmperageLimitMin; } + // Return the maximal value + return Utils.getChargingStationAmperage(chargingStation, null, connector.connectorId); } private static async setConnectorPhaseAssignment(tenant: Tenant, chargingStation: ChargingStation, connector: Connector, nrOfPhases?: number): Promise { @@ -1894,7 +1838,5 @@ export default class OCPPUtils { chargePoint.power += connector.power; chargePoint.connectorIDs.push(connector.connectorId); } - // Reset Charging Station - chargingStation.maximumPower = chargePoint.power; } } diff --git a/src/server/ocpp/validation/OCPPValidation.ts b/src/server/ocpp/validation/OCPPValidation.ts index b41fa58751..d7d7edee0d 100644 --- a/src/server/ocpp/validation/OCPPValidation.ts +++ b/src/server/ocpp/validation/OCPPValidation.ts @@ -27,6 +27,7 @@ export default class OCPPValidation extends SchemaValidator { private heartbeatRequest: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/ocpp/schemas/heartbeat-request.json`, 'utf8')); private firmwareStatusNotificationRequest: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/ocpp/schemas/firmware-status-notification-request.json`, 'utf8')); private dataTransferRequest: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/ocpp/schemas/data-transfert-request.json`, 'utf8')); + private meterValueRequest: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/ocpp/schemas/meter-values-request.json`, 'utf8')); private constructor() { super('OCPPValidation'); @@ -107,7 +108,7 @@ export default class OCPPValidation extends SchemaValidator { public async validateMeterValues(tenantID: string, chargingStation: ChargingStation, meterValues: OCPPMeterValuesRequestExtended): Promise { // Always integer - meterValues.connectorId = Utils.convertToInt(meterValues.connectorId); + this.validate(this.meterValueRequest, meterValues); // Check Connector ID if (meterValues.connectorId === 0) { // KEBA: Connector ID must be > 0 according to OCPP @@ -131,12 +132,12 @@ export default class OCPPValidation extends SchemaValidator { action: ServerAction.OCPP_METER_VALUES, message: `Connector ID '${meterValues.connectorId}' not found for Transaction ID '${meterValues.transactionId}'` }); + return; } // Transaction ID is provided on Connector - if (foundConnector.currentTransactionID > 0) { + if (foundConnector?.currentTransactionID > 0) { // Check if provided in Meter Values - meterValues.transactionId = Utils.convertToInt(meterValues.transactionId); - if (meterValues.transactionId === 0 && foundConnector.currentTransactionID > 0) { + if (Utils.isNullOrUndefined(meterValues.transactionId) && foundConnector.currentTransactionID > 0) { // Reuse Transaction ID from Connector meterValues.transactionId = foundConnector.currentTransactionID; await Logging.logWarning({ diff --git a/src/server/rest/RestServer.ts b/src/server/rest/RestServer.ts index bf166510f6..53408f84b1 100644 --- a/src/server/rest/RestServer.ts +++ b/src/server/rest/RestServer.ts @@ -1,10 +1,8 @@ -import { Application, NextFunction, Request, Response } from 'express'; - +import { Application } from 'express'; import AuthService from './v1/service/AuthService'; import CentralSystemRestServiceConfiguration from '../../types/configuration/CentralSystemRestServiceConfiguration'; import ExpressUtils from '../ExpressUtils'; import GlobalRouterV1 from './v1/router/GlobalRouterV1'; -import Logging from '../../utils/Logging'; import RestServerService from './RestServerService'; import { ServerType } from '../../types/Server'; import { ServerUtils } from '../ServerUtils'; diff --git a/src/server/rest/RestServerService.ts b/src/server/rest/RestServerService.ts index 4b9510edab..79c47b3d11 100644 --- a/src/server/rest/RestServerService.ts +++ b/src/server/rest/RestServerService.ts @@ -8,7 +8,7 @@ import CompanyService from './v1/service/CompanyService'; import ConnectionService from './v1/service/ConnectionService'; import Constants from '../../utils/Constants'; import Logging from '../../utils/Logging'; -import LoggingService from './v1/service/LoggingService'; +import LogService from './v1/service/LogService'; import NotificationService from './v1/service/NotificationService'; import OCPIEndpointService from './v1/service/OCPIEndpointService'; import OICPEndpointService from './v1/service/OICPEndpointService'; @@ -83,9 +83,9 @@ class RequestMapper { case 'GET': // Register REST actions this.registerJsonActionsPaths({ - [ServerAction.LOGGINGS]: LoggingService.handleGetLogs.bind(this), - [ServerAction.LOGGING]: LoggingService.handleGetLog.bind(this), - [ServerAction.LOGGINGS_EXPORT]: LoggingService.handleExportLogs.bind(this), + [ServerAction.LOGS]: LogService.handleGetLogs.bind(this), + [ServerAction.LOG]: LogService.handleGetLog.bind(this), + [ServerAction.LOGS_EXPORT]: LogService.handleExportLogs.bind(this), [ServerAction.CHARGING_STATIONS]: ChargingStationService.handleGetChargingStations.bind(this), [ServerAction.CAR_CATALOGS]: CarService.handleGetCarCatalogs.bind(this), [ServerAction.CAR_CATALOG]: CarService.handleGetCarCatalog.bind(this), diff --git a/src/server/rest/v1/router/GlobalRouterV1.ts b/src/server/rest/v1/router/GlobalRouterV1.ts index 1cd4c8991a..051ebcbcc4 100644 --- a/src/server/rest/v1/router/GlobalRouterV1.ts +++ b/src/server/rest/v1/router/GlobalRouterV1.ts @@ -1,5 +1,3 @@ -import express, { NextFunction, Request, Response } from 'express'; - import AssetRouter from './api/AssetRouter'; import AuthRouter from './auth/AuthRouter'; import AuthService from '../service/AuthService'; @@ -8,8 +6,7 @@ import CarRouter from './api/CarRouter'; import ChargingStationRouter from './api/ChargingStationRouter'; import CompanyRouter from './api/CompanyRouter'; import ConnectionRouter from './api/ConnectionRouter'; -import Logging from '../../../../utils/Logging'; -import LoggingRouter from './api/LoggingRouter'; +import LoggingRouter from './api/LogRouter'; import NotificationRouter from './api/NotificationRouter'; import OCPIEndpointRouter from './api/OCPIEndpointRouter'; import OICPEndpointRouter from './api/OICPEndpointRouter'; @@ -26,6 +23,7 @@ import TenantRouter from './api/TenantRouter'; import TransactionRouter from './api/TransactionRouter'; import UserRouter from './api/UserRouter'; import UtilRouter from './util/UtilRouter'; +import express from 'express'; export default class GlobalRouterV1 { private router: express.Router; diff --git a/src/server/rest/v1/router/api/AssetRouter.ts b/src/server/rest/v1/router/api/AssetRouter.ts index 84dd75c3df..a3f27e3619 100644 --- a/src/server/rest/v1/router/api/AssetRouter.ts +++ b/src/server/rest/v1/router/api/AssetRouter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; import express, { NextFunction, Request, Response } from 'express'; @@ -27,69 +26,69 @@ export default class AssetRouter { } private buildRouteCreateAssetConsumption(): void { - this.router.post(`/${RESTServerRoute.REST_ASSET_CONSUMPTIONS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.post(`/${RESTServerRoute.REST_ASSET_CONSUMPTIONS}`, (req: Request, res: Response, next: NextFunction) => { req.query.assetID = req.params.id; - await RouterUtils.handleRestServerAction(AssetService.handleCreateAssetConsumption.bind(this), ServerAction.ASSET_CONSUMPTION, req, res, next); + void RouterUtils.handleRestServerAction(AssetService.handleCreateAssetConsumption.bind(this), ServerAction.ASSET_CONSUMPTION, req, res, next); }); } private buildRouteCreateAsset(): void { - this.router.post(`/${RESTServerRoute.REST_ASSETS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(AssetService.handleCreateAsset.bind(this), ServerAction.ASSET_CREATE, req, res, next); + this.router.post(`/${RESTServerRoute.REST_ASSETS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(AssetService.handleCreateAsset.bind(this), ServerAction.ASSET_CREATE, req, res, next); }); } private buildRouteGetAssets(): void { - this.router.get(`/${RESTServerRoute.REST_ASSETS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(AssetService.handleGetAssets.bind(this), ServerAction.ASSETS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_ASSETS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(AssetService.handleGetAssets.bind(this), ServerAction.ASSETS, req, res, next); }); } private buildRouteGetAsset(): void { - this.router.get(`/${RESTServerRoute.REST_ASSET}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_ASSET}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(AssetService.handleGetAsset.bind(this), ServerAction.ASSET, req, res, next); + void RouterUtils.handleRestServerAction(AssetService.handleGetAsset.bind(this), ServerAction.ASSET, req, res, next); }); } private buildRouteGetAssetsInError(): void { - this.router.get(`/${RESTServerRoute.REST_ASSETS_IN_ERROR}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(AssetService.handleGetAssetsInError.bind(this), ServerAction.ASSETS_IN_ERROR, req, res, next); + this.router.get(`/${RESTServerRoute.REST_ASSETS_IN_ERROR}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(AssetService.handleGetAssetsInError.bind(this), ServerAction.ASSETS_IN_ERROR, req, res, next); }); } private buildRouteCheckAssetConnection(): void { - this.router.get(`/${RESTServerRoute.REST_ASSET_CHECK_CONNECTION}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_ASSET_CHECK_CONNECTION}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(AssetService.handleCheckAssetConnection.bind(this), ServerAction.CHECK_ASSET_CONNECTION, req, res, next); + void RouterUtils.handleRestServerAction(AssetService.handleCheckAssetConnection.bind(this), ServerAction.CHECK_ASSET_CONNECTION, req, res, next); }); } private buildRouteGetAssetLastConsumption(): void { - this.router.get(`/${RESTServerRoute.REST_ASSET_RETRIEVE_CONSUMPTION}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_ASSET_RETRIEVE_CONSUMPTION}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(AssetService.handleRetrieveConsumption.bind(this), ServerAction.RETRIEVE_ASSET_CONSUMPTION, req, res, next); + void RouterUtils.handleRestServerAction(AssetService.handleRetrieveConsumption.bind(this), ServerAction.RETRIEVE_ASSET_CONSUMPTION, req, res, next); }); } private buildRouteGetAssetConsumptions(): void { - this.router.get(`/${RESTServerRoute.REST_ASSET_CONSUMPTIONS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_ASSET_CONSUMPTIONS}`, (req: Request, res: Response, next: NextFunction) => { req.query.AssetID = req.params.id; - await RouterUtils.handleRestServerAction(AssetService.handleGetAssetConsumption.bind(this), ServerAction.ASSET_CONSUMPTION, req, res, next); + void RouterUtils.handleRestServerAction(AssetService.handleGetAssetConsumption.bind(this), ServerAction.ASSET_CONSUMPTION, req, res, next); }); } private buildRouteUpdateAsset(): void { - this.router.put(`/${RESTServerRoute.REST_ASSET}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_ASSET}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(AssetService.handleUpdateAsset.bind(this), ServerAction.ASSET_UPDATE, req, res, next); + void RouterUtils.handleRestServerAction(AssetService.handleUpdateAsset.bind(this), ServerAction.ASSET_UPDATE, req, res, next); }); } private buildRouteDeleteAsset(): void { - this.router.delete(`/${RESTServerRoute.REST_ASSET}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.delete(`/${RESTServerRoute.REST_ASSET}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(AssetService.handleDeleteAsset.bind(this), ServerAction.ASSET_DELETE, req, res, next); + void RouterUtils.handleRestServerAction(AssetService.handleDeleteAsset.bind(this), ServerAction.ASSET_DELETE, req, res, next); }); } } diff --git a/src/server/rest/v1/router/api/CarRouter.ts b/src/server/rest/v1/router/api/CarRouter.ts index 0a1e51ee20..076e4c6d58 100644 --- a/src/server/rest/v1/router/api/CarRouter.ts +++ b/src/server/rest/v1/router/api/CarRouter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; import express, { NextFunction, Request, Response } from 'express'; @@ -27,67 +26,67 @@ export default class CarRouter { } private buildRouteGetCarCatalogs(): void { - this.router.get(`/${RESTServerRoute.REST_CAR_CATALOGS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(CarService.handleGetCarCatalogs.bind(this), ServerAction.CAR_CATALOGS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_CAR_CATALOGS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(CarService.handleGetCarCatalogs.bind(this), ServerAction.CAR_CATALOGS, req, res, next); }); } private buildRouteGetCarCatalog(): void { - this.router.get(`/${RESTServerRoute.REST_CAR_CATALOG}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_CAR_CATALOG}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(CarService.handleGetCarCatalog.bind(this), ServerAction.CAR_CATALOG, req, res, next); + void RouterUtils.handleRestServerAction(CarService.handleGetCarCatalog.bind(this), ServerAction.CAR_CATALOG, req, res, next); }); } private buildRouteGetCarCatalogImages(): void { - this.router.get(`/${RESTServerRoute.REST_CAR_CATALOG_IMAGES}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_CAR_CATALOG_IMAGES}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(CarService.handleGetCarCatalogImages.bind(this), ServerAction.CAR_CATALOG_IMAGES, req, res, next); + void RouterUtils.handleRestServerAction(CarService.handleGetCarCatalogImages.bind(this), ServerAction.CAR_CATALOG_IMAGES, req, res, next); }); } private buildRouteCarCatalogsSynchronize(): void { - this.router.put(`/${RESTServerRoute.REST_CAR_CATALOG_SYNCHRONIZE}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(CarService.handleSynchronizeCarCatalogs.bind(this), ServerAction.CAR_CATALOG_SYNCHRONIZATION, req, res, next); + this.router.put(`/${RESTServerRoute.REST_CAR_CATALOG_SYNCHRONIZE}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(CarService.handleSynchronizeCarCatalogs.bind(this), ServerAction.CAR_CATALOG_SYNCHRONIZATION, req, res, next); }); } private buildRouteGetCarMakers(): void { - this.router.get(`/${RESTServerRoute.REST_CAR_MAKERS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(CarService.handleGetCarMakers.bind(this), ServerAction.CAR_MAKERS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_CAR_MAKERS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(CarService.handleGetCarMakers.bind(this), ServerAction.CAR_MAKERS, req, res, next); }); } private buildRouteCreateCar(): void { - this.router.post(`/${RESTServerRoute.REST_CARS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(CarService.handleCreateCar.bind(this), ServerAction.CAR_CREATE, req, res, next); + this.router.post(`/${RESTServerRoute.REST_CARS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(CarService.handleCreateCar.bind(this), ServerAction.CAR_CREATE, req, res, next); }); } private buildRouteGetCars(): void { - this.router.get(`/${RESTServerRoute.REST_CARS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(CarService.handleGetCars.bind(this), ServerAction.CARS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_CARS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(CarService.handleGetCars.bind(this), ServerAction.CARS, req, res, next); }); } private buildRouteGetCar(): void { - this.router.get(`/${RESTServerRoute.REST_CAR}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_CAR}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(CarService.handleGetCar.bind(this), ServerAction.CAR, req, res, next); + void RouterUtils.handleRestServerAction(CarService.handleGetCar.bind(this), ServerAction.CAR, req, res, next); }); } private buildRouteUpdateCar(): void { - this.router.put(`/${RESTServerRoute.REST_CAR}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_CAR}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(CarService.handleUpdateCar.bind(this), ServerAction.CAR_UPDATE, req, res, next); + void RouterUtils.handleRestServerAction(CarService.handleUpdateCar.bind(this), ServerAction.CAR_UPDATE, req, res, next); }); } private buildRouteDeleteCar(): void { - this.router.delete(`/${RESTServerRoute.REST_CAR}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.delete(`/${RESTServerRoute.REST_CAR}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(CarService.handleDeleteCar.bind(this), ServerAction.CAR_DELETE, req, res, next); + void RouterUtils.handleRestServerAction(CarService.handleDeleteCar.bind(this), ServerAction.CAR_DELETE, req, res, next); }); } } diff --git a/src/server/rest/v1/router/api/ChargingStationRouter.ts b/src/server/rest/v1/router/api/ChargingStationRouter.ts index 43b1c08186..e79b301c1f 100644 --- a/src/server/rest/v1/router/api/ChargingStationRouter.ts +++ b/src/server/rest/v1/router/api/ChargingStationRouter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; import express, { NextFunction, Request, Response } from 'express'; @@ -53,236 +52,236 @@ export default class ChargingStationRouter { } private buildRouteChargingStations(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(ChargingStationService.handleGetChargingStations.bind(this), ServerAction.CHARGING_STATIONS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(ChargingStationService.handleGetChargingStations.bind(this), ServerAction.CHARGING_STATIONS, req, res, next); }); } private buildRouteChargingStation(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_STATION}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_CHARGING_STATION}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(ChargingStationService.handleGetChargingStation.bind(this), ServerAction.CHARGING_STATION, req, res, next); + void RouterUtils.handleRestServerAction(ChargingStationService.handleGetChargingStation.bind(this), ServerAction.CHARGING_STATION, req, res, next); }); } private buildRouteChargingStationDelete(): void { - this.router.delete(`/${RESTServerRoute.REST_CHARGING_STATIONS}/:id`, async (req: Request, res: Response, next: NextFunction) => { + this.router.delete(`/${RESTServerRoute.REST_CHARGING_STATIONS}/:id`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(ChargingStationService.handleDeleteChargingStation.bind(this), ServerAction.CHARGING_STATION_DELETE, req, res, next); + void RouterUtils.handleRestServerAction(ChargingStationService.handleDeleteChargingStation.bind(this), ServerAction.CHARGING_STATION_DELETE, req, res, next); }); } private buildRouteChargingStationReset(): void { - this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_RESET}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_RESET}`, (req: Request, res: Response, next: NextFunction) => { req.body.chargingStationID = req.params.id; - await RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_RESET, req, res, next); + void RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_RESET, req, res, next); }); } private buildRouteChargingStationClearCache(): void { - this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_CACHE_CLEAR}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_CACHE_CLEAR}`, (req: Request, res: Response, next: NextFunction) => { req.body.chargingStationID = req.params.id; - await RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_CLEAR_CACHE, req, res, next); + void RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_CLEAR_CACHE, req, res, next); }); } private buildRouteChargingStationTriggerDataTransfer(): void { - this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_TRIGGER_DATA_TRANSFER}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_TRIGGER_DATA_TRANSFER}`, (req: Request, res: Response, next: NextFunction) => { req.body.chargingStationID = req.params.id; - await RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_TRIGGER_DATA_TRANSFER, req, res, next); + void RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_TRIGGER_DATA_TRANSFER, req, res, next); }); } private buildRouteChargingStationRetrieveConfiguration(): void { - this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_RETRIEVE_CONFIGURATION}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_RETRIEVE_CONFIGURATION}`, (req: Request, res: Response, next: NextFunction) => { req.body.chargingStationID = req.params.id; - await RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_GET_CONFIGURATION, req, res, next); + void RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_GET_CONFIGURATION, req, res, next); }); } private buildRouteChargingStationChangeConfiguration(): void { - this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_CHANGE_CONFIGURATION}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_CHANGE_CONFIGURATION}`, (req: Request, res: Response, next: NextFunction) => { req.body.chargingStationID = req.params.id; - await RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_CHANGE_CONFIGURATION, req, res, next); + void RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_CHANGE_CONFIGURATION, req, res, next); }); } private buildRouteChargingStationRemoteStart(): void { - this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_REMOTE_START}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_REMOTE_START}`, (req: Request, res: Response, next: NextFunction) => { req.body.chargingStationID = req.params.id; - await RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_REMOTE_START_TRANSACTION, req, res, next); + void RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_REMOTE_START_TRANSACTION, req, res, next); }); } private buildRouteChargingStationRemoteStop(): void { - this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_REMOTE_STOP}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_REMOTE_STOP}`, (req: Request, res: Response, next: NextFunction) => { req.body.chargingStationID = req.params.id; - await RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_REMOTE_STOP_TRANSACTION, req, res, next); + void RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_REMOTE_STOP_TRANSACTION, req, res, next); }); } private buildRouteChargingStationUnlockConnector(): void { - this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_UNLOCK_CONNECTOR}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_UNLOCK_CONNECTOR}`, (req: Request, res: Response, next: NextFunction) => { req.body.chargingStationID = req.params.id; req.body.args = { ...req.body.args, connectorId: req.params.connectorId }; - await RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_UNLOCK_CONNECTOR, req, res, next); + void RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_UNLOCK_CONNECTOR, req, res, next); }); } private buildRouteChargingStationGetCompositeSchedule(): void { - this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_GET_COMPOSITE_SCHEDULE}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_GET_COMPOSITE_SCHEDULE}`, (req: Request, res: Response, next: NextFunction) => { req.body.chargingStationID = req.params.id; - await RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_GET_COMPOSITE_SCHEDULE, req, res, next); + void RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_GET_COMPOSITE_SCHEDULE, req, res, next); }); } private buildRouteChargingStationGetDiagnostics(): void { - this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_GET_DIAGNOSTICS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_GET_DIAGNOSTICS}`, (req: Request, res: Response, next: NextFunction) => { req.body.chargingStationID = req.params.id; - await RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_GET_DIAGNOSTICS, req, res, next); + void RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_GET_DIAGNOSTICS, req, res, next); }); } private buildRouteChargingStationUpdateFirmware(): void { - this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_FIRMWARE_UPDATE}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_FIRMWARE_UPDATE}`, (req: Request, res: Response, next: NextFunction) => { req.body.chargingStationID = req.params.id; - await RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_UPDATE_FIRMWARE, req, res, next); + void RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_UPDATE_FIRMWARE, req, res, next); }); } private buildRouteChargingStationChangeAvailability(): void { - this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_CHANGE_AVAILABILITY}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_CHANGE_AVAILABILITY}`, (req: Request, res: Response, next: NextFunction) => { req.body.chargingStationID = req.params.id; - await RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_CHANGE_AVAILABILITY, req, res, next); + void RouterUtils.handleRestServerAction(ChargingStationService.handleOcppAction.bind(this), ServerAction.CHARGING_STATION_CHANGE_AVAILABILITY, req, res, next); }); } private buildRouteChargingStationGenerateQRCode(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS_QRCODE_GENERATE}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS_QRCODE_GENERATE}`, (req: Request, res: Response, next: NextFunction) => { req.query.ChargingStationID = req.params.id; req.query.ConnectorID = req.params.connectorId; - await RouterUtils.handleRestServerAction(ChargingStationService.handleGenerateQrCodeForConnector.bind(this), ServerAction.GENERATE_QR_CODE_FOR_CONNECTOR, req, res, next); + void RouterUtils.handleRestServerAction(ChargingStationService.handleGenerateQrCodeForConnector.bind(this), ServerAction.GENERATE_QR_CODE_FOR_CONNECTOR, req, res, next); }); } private buildRouteChargingStationDownloadQRCode(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS_QRCODE_DOWNLOAD}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(ChargingStationService.handleDownloadQrCodesPdf.bind(this), ServerAction.CHARGING_STATION_DOWNLOAD_QR_CODE_PDF, req, res, next); + this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS_QRCODE_DOWNLOAD}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(ChargingStationService.handleDownloadQrCodesPdf.bind(this), ServerAction.CHARGING_STATION_DOWNLOAD_QR_CODE_PDF, req, res, next); }); } private buildRouteChargingStationGetOCPPParameters(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_STATION_GET_OCPP_PARAMETERS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_CHARGING_STATION_GET_OCPP_PARAMETERS}`, (req: Request, res: Response, next: NextFunction) => { req.query.ChargingStationID = req.params.id; - await RouterUtils.handleRestServerAction(ChargingStationService.handleGetChargingStationOcppParameters.bind(this), + void RouterUtils.handleRestServerAction(ChargingStationService.handleGetChargingStationOcppParameters.bind(this), ServerAction.CHARGING_STATIONS_OCPP_PARAMETERS, req, res, next); }); } private buildRouteChargingStationRequestOCPPParameters(): void { - this.router.post(`/${RESTServerRoute.REST_CHARGING_STATIONS_REQUEST_OCPP_PARAMETERS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(ChargingStationService.handleRequestChargingStationOcppParameters.bind(this), + this.router.post(`/${RESTServerRoute.REST_CHARGING_STATIONS_REQUEST_OCPP_PARAMETERS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(ChargingStationService.handleRequestChargingStationOcppParameters.bind(this), ServerAction.CHARGING_STATION_REQUEST_OCPP_PARAMETERS, req, res, next); }); } private buildRouteChargingStationExportOCPPParameters(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS_EXPORT_OCPP_PARAMETERS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(ChargingStationService.handleExportChargingStationsOCPPParams.bind(this), + this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS_EXPORT_OCPP_PARAMETERS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(ChargingStationService.handleExportChargingStationsOCPPParams.bind(this), ServerAction.CHARGING_STATIONS_OCPP_PARAMS_EXPORT, req, res, next); }); } private buildRouteChargingStationUpdateParameters(): void { - this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_UPDATE_PARAMETERS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(ChargingStationService.handleUpdateChargingStationParams.bind(this), ServerAction.CHARGING_STATION_UPDATE_PARAMS, req, res, next); + this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_UPDATE_PARAMETERS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(ChargingStationService.handleUpdateChargingStationParams.bind(this), ServerAction.CHARGING_STATION_UPDATE_PARAMS, req, res, next); }); } private buildRouteChargingStationLimitPower(): void { - this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_POWER_LIMIT}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_POWER_LIMIT}`, (req: Request, res: Response, next: NextFunction) => { req.body.chargingStationID = req.params.id; - await RouterUtils.handleRestServerAction(ChargingStationService.handleChargingStationLimitPower.bind(this), ServerAction.CHARGING_STATION_LIMIT_POWER, req, res, next); + void RouterUtils.handleRestServerAction(ChargingStationService.handleChargingStationLimitPower.bind(this), ServerAction.CHARGING_STATION_LIMIT_POWER, req, res, next); }); } private buildRouteChargingStationTransactions(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS_TRANSACTIONS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS_TRANSACTIONS}`, (req: Request, res: Response, next: NextFunction) => { req.query.ChargingStationID = req.params.id; - await RouterUtils.handleRestServerAction(TransactionService.handleGetChargingStationTransactions.bind(this), ServerAction.CHARGING_STATION_TRANSACTIONS, req, res, next); + void RouterUtils.handleRestServerAction(TransactionService.handleGetChargingStationTransactions.bind(this), ServerAction.CHARGING_STATION_TRANSACTIONS, req, res, next); }); } private buildRouteChargingStationsInError(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS_IN_ERROR}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(ChargingStationService.handleGetChargingStationsInError.bind(this), ServerAction.CHARGING_STATIONS_IN_ERROR, req, res, next); + this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS_IN_ERROR}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(ChargingStationService.handleGetChargingStationsInError.bind(this), ServerAction.CHARGING_STATIONS_IN_ERROR, req, res, next); }); } private buildRouteChargingStationsExport(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS_EXPORT}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(ChargingStationService.handleExportChargingStations.bind(this), ServerAction.CHARGING_STATIONS_EXPORT, req, res, next); + this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS_EXPORT}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(ChargingStationService.handleExportChargingStations.bind(this), ServerAction.CHARGING_STATIONS_EXPORT, req, res, next); }); } private buildRouteChargingStationCheckSmartCharging(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_STATION_CHECK_SMART_CHARGING_CONNECTION}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(ChargingStationService.handleCheckSmartChargingConnection.bind(this), ServerAction.CHECK_SMART_CHARGING_CONNECTION, req, res, next); + this.router.get(`/${RESTServerRoute.REST_CHARGING_STATION_CHECK_SMART_CHARGING_CONNECTION}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(ChargingStationService.handleCheckSmartChargingConnection.bind(this), ServerAction.CHECK_SMART_CHARGING_CONNECTION, req, res, next); }); } private buildRouteChargingStationTriggerSmartCharging(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_STATION_TRIGGER_SMART_CHARGING}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(ChargingStationService.handleTriggerSmartCharging.bind(this), ServerAction.TRIGGER_SMART_CHARGING, req, res, next); + this.router.get(`/${RESTServerRoute.REST_CHARGING_STATION_TRIGGER_SMART_CHARGING}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(ChargingStationService.handleTriggerSmartCharging.bind(this), ServerAction.TRIGGER_SMART_CHARGING, req, res, next); }); } private buildRouteChargingStationGetChargingProfiles(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_PROFILES}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(ChargingStationService.handleGetChargingProfiles.bind(this), ServerAction.CHARGING_PROFILES, req, res, next); + this.router.get(`/${RESTServerRoute.REST_CHARGING_PROFILES}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(ChargingStationService.handleGetChargingProfiles.bind(this), ServerAction.CHARGING_PROFILES, req, res, next); }); } private buildRouteChargingStationCreateChargingProfile(): void { - this.router.post(`/${RESTServerRoute.REST_CHARGING_PROFILES}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(ChargingStationService.handleCreateChargingProfile.bind(this), ServerAction.CHARGING_PROFILE_CREATE, req, res, next); + this.router.post(`/${RESTServerRoute.REST_CHARGING_PROFILES}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(ChargingStationService.handleCreateChargingProfile.bind(this), ServerAction.CHARGING_PROFILE_CREATE, req, res, next); }); } private buildRouteChargingStationUpdateChargingProfile(): void { - this.router.put(`/${RESTServerRoute.REST_CHARGING_PROFILE}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(ChargingStationService.handleUpdateChargingProfile.bind(this), ServerAction.CHARGING_PROFILE_UPDATE, req, res, next); + this.router.put(`/${RESTServerRoute.REST_CHARGING_PROFILE}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(ChargingStationService.handleUpdateChargingProfile.bind(this), ServerAction.CHARGING_PROFILE_UPDATE, req, res, next); }); } private buildRouteChargingStationDeleteChargingProfile(): void { - this.router.delete(`/${RESTServerRoute.REST_CHARGING_PROFILE}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.delete(`/${RESTServerRoute.REST_CHARGING_PROFILE}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(ChargingStationService.handleDeleteChargingProfile.bind(this), ServerAction.CHARGING_PROFILE_DELETE, req, res, next); + void RouterUtils.handleRestServerAction(ChargingStationService.handleDeleteChargingProfile.bind(this), ServerAction.CHARGING_PROFILE_DELETE, req, res, next); }); } private buildRouteChargingStationGetBootNotifications(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS_BOOT_NOTIFICATIONS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(ChargingStationService.handleGetBootNotifications.bind(this), ServerAction.BOOT_NOTIFICATIONS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS_BOOT_NOTIFICATIONS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(ChargingStationService.handleGetBootNotifications.bind(this), ServerAction.BOOT_NOTIFICATIONS, req, res, next); }); } private buildRouteChargingStationGetStatusNotifications(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS_STATUS_NOTIFICATIONS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(ChargingStationService.handleGetStatusNotifications.bind(this), ServerAction.STATUS_NOTIFICATIONS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS_STATUS_NOTIFICATIONS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(ChargingStationService.handleGetStatusNotifications.bind(this), ServerAction.STATUS_NOTIFICATIONS, req, res, next); }); } private buildRouteChargingStationReserveNow(): void { - this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_RESERVE_NOW}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(ChargingStationService.handleReserveNow.bind(this), ServerAction.CHARGING_STATION_RESERVE_NOW, req, res, next); + this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_RESERVE_NOW}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(ChargingStationService.handleReserveNow.bind(this), ServerAction.CHARGING_STATION_RESERVE_NOW, req, res, next); }); } private buildRouteChargingStationCancelReservation(): void { - this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_CANCEL_RESERVATION}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(ChargingStationService.handleCancelReservation.bind(this), ServerAction.CHARGING_STATION_CANCEL_RESERVATION, req, res, next); + this.router.put(`/${RESTServerRoute.REST_CHARGING_STATIONS_CANCEL_RESERVATION}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(ChargingStationService.handleCancelReservation.bind(this), ServerAction.CHARGING_STATION_CANCEL_RESERVATION, req, res, next); }); } } diff --git a/src/server/rest/v1/router/api/CompanyRouter.ts b/src/server/rest/v1/router/api/CompanyRouter.ts index 1e268efb4b..587a2fe09e 100644 --- a/src/server/rest/v1/router/api/CompanyRouter.ts +++ b/src/server/rest/v1/router/api/CompanyRouter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; import express, { NextFunction, Request, Response } from 'express'; @@ -22,35 +21,35 @@ export default class CompanyRouter { } private buildRouteCompanies(): void { - this.router.get(`/${RESTServerRoute.REST_COMPANIES}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(CompanyService.handleGetCompanies.bind(this), ServerAction.COMPANIES, req, res, next); + this.router.get(`/${RESTServerRoute.REST_COMPANIES}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(CompanyService.handleGetCompanies.bind(this), ServerAction.COMPANIES, req, res, next); }); } private buildRouteCompany(): void { - this.router.get(`/${RESTServerRoute.REST_COMPANY}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_COMPANY}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(CompanyService.handleGetCompany.bind(this), ServerAction.COMPANY, req, res, next); + void RouterUtils.handleRestServerAction(CompanyService.handleGetCompany.bind(this), ServerAction.COMPANY, req, res, next); }); } private buildRouteCreateCompany(): void { - this.router.post(`/${RESTServerRoute.REST_COMPANIES}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(CompanyService.handleCreateCompany.bind(this), ServerAction.COMPANY_CREATE, req, res, next); + this.router.post(`/${RESTServerRoute.REST_COMPANIES}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(CompanyService.handleCreateCompany.bind(this), ServerAction.COMPANY_CREATE, req, res, next); }); } private buildRouteUpdateCompany(): void { - this.router.put(`/${RESTServerRoute.REST_COMPANY}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_COMPANY}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(CompanyService.handleUpdateCompany.bind(this), ServerAction.COMPANY_UPDATE, req, res, next); + void RouterUtils.handleRestServerAction(CompanyService.handleUpdateCompany.bind(this), ServerAction.COMPANY_UPDATE, req, res, next); }); } private buildRouteDeleteCompany(): void { - this.router.delete(`/${RESTServerRoute.REST_COMPANY}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.delete(`/${RESTServerRoute.REST_COMPANY}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(CompanyService.handleDeleteCompany.bind(this), ServerAction.COMPANY_DELETE, req, res, next); + void RouterUtils.handleRestServerAction(CompanyService.handleDeleteCompany.bind(this), ServerAction.COMPANY_DELETE, req, res, next); }); } } diff --git a/src/server/rest/v1/router/api/ConnectionRouter.ts b/src/server/rest/v1/router/api/ConnectionRouter.ts index f09f51d26c..1c7a2ab874 100644 --- a/src/server/rest/v1/router/api/ConnectionRouter.ts +++ b/src/server/rest/v1/router/api/ConnectionRouter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; import express, { NextFunction, Request, Response } from 'express'; @@ -22,28 +21,28 @@ export default class ConnectionRouter { } private buildRouteConnections(): void { - this.router.get(`/${RESTServerRoute.REST_CONNECTIONS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(ConnectionService.handleGetConnections.bind(this), ServerAction.INTEGRATION_CONNECTIONS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_CONNECTIONS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(ConnectionService.handleGetConnections.bind(this), ServerAction.INTEGRATION_CONNECTIONS, req, res, next); }); } private buildRouteConnection(): void { - this.router.get(`/${RESTServerRoute.REST_CONNECTION}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_CONNECTION}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = sanitize(req.params.id); - await RouterUtils.handleRestServerAction(ConnectionService.handleGetConnection.bind(this), ServerAction.INTEGRATION_CONNECTION, req, res, next); + void RouterUtils.handleRestServerAction(ConnectionService.handleGetConnection.bind(this), ServerAction.INTEGRATION_CONNECTION, req, res, next); }); } private buildRouteCreateConnection(): void { - this.router.post(`/${RESTServerRoute.REST_CONNECTIONS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(ConnectionService.handleCreateConnection.bind(this), ServerAction.INTEGRATION_CONNECTION_CREATE, req, res, next); + this.router.post(`/${RESTServerRoute.REST_CONNECTIONS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(ConnectionService.handleCreateConnection.bind(this), ServerAction.INTEGRATION_CONNECTION_CREATE, req, res, next); }); } private buildRouteDeleteConnection(): void { - this.router.delete(`/${RESTServerRoute.REST_CONNECTION}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.delete(`/${RESTServerRoute.REST_CONNECTION}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = sanitize(req.params.id); - await RouterUtils.handleRestServerAction(ConnectionService.handleDeleteConnection.bind(this), ServerAction.INTEGRATION_CONNECTION_DELETE, req, res, next); + void RouterUtils.handleRestServerAction(ConnectionService.handleDeleteConnection.bind(this), ServerAction.INTEGRATION_CONNECTION_DELETE, req, res, next); }); } } diff --git a/src/server/rest/v1/router/api/LogRouter.ts b/src/server/rest/v1/router/api/LogRouter.ts new file mode 100644 index 0000000000..36f739aa2d --- /dev/null +++ b/src/server/rest/v1/router/api/LogRouter.ts @@ -0,0 +1,39 @@ +import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; +import express, { NextFunction, Request, Response } from 'express'; + +import LogService from '../../service/LogService'; +import RouterUtils from '../../../../../utils/RouterUtils'; + +export default class LoggingRouter { + private router: express.Router; + + public constructor() { + this.router = express.Router(); + } + + public buildRoutes(): express.Router { + this.buildRouteLogs(); + this.buildRouteLog(); + this.buildRouteLogsExport(); + return this.router; + } + + private buildRouteLogs(): void { + this.router.get(`/${RESTServerRoute.REST_LOGS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(LogService.handleGetLogs.bind(this), ServerAction.LOGS, req, res, next); + }); + } + + private buildRouteLog(): void { + this.router.get(`/${RESTServerRoute.REST_LOG}`, (req: Request, res: Response, next: NextFunction) => { + req.query.ID = req.params.id; + void RouterUtils.handleRestServerAction(LogService.handleGetLog.bind(this), ServerAction.LOG, req, res, next); + }); + } + + private buildRouteLogsExport(): void { + this.router.get(`/${RESTServerRoute.REST_LOGS_EXPORT}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(LogService.handleExportLogs.bind(this), ServerAction.LOGS_EXPORT, req, res, next); + }); + } +} diff --git a/src/server/rest/v1/router/api/LoggingRouter.ts b/src/server/rest/v1/router/api/LoggingRouter.ts deleted file mode 100644 index eefc88eb3d..0000000000 --- a/src/server/rest/v1/router/api/LoggingRouter.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ -import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; -import express, { NextFunction, Request, Response } from 'express'; - -import LoggingService from '../../service/LoggingService'; -import RouterUtils from '../../../../../utils/RouterUtils'; - -export default class LoggingRouter { - private router: express.Router; - - public constructor() { - this.router = express.Router(); - } - - public buildRoutes(): express.Router { - this.buildRouteLoggings(); - this.buildRouteLogging(); - this.buildRouteLoggingsExport(); - return this.router; - } - - private buildRouteLoggings(): void { - this.router.get(`/${RESTServerRoute.REST_LOGGINGS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(LoggingService.handleGetLogs.bind(this), ServerAction.LOGGINGS, req, res, next); - }); - } - - private buildRouteLogging(): void { - this.router.get(`/${RESTServerRoute.REST_LOGGING}`, async (req: Request, res: Response, next: NextFunction) => { - req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(LoggingService.handleGetLog.bind(this), ServerAction.LOGGING, req, res, next); - }); - } - - private buildRouteLoggingsExport(): void { - this.router.get(`/${RESTServerRoute.REST_LOGGINGS_EXPORT}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(LoggingService.handleExportLogs.bind(this), ServerAction.LOGGINGS_EXPORT, req, res, next); - }); - } -} diff --git a/src/server/rest/v1/router/api/NotificationRouter.ts b/src/server/rest/v1/router/api/NotificationRouter.ts index a8b084a848..65ee14582a 100644 --- a/src/server/rest/v1/router/api/NotificationRouter.ts +++ b/src/server/rest/v1/router/api/NotificationRouter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; import express, { NextFunction, Request, Response } from 'express'; @@ -19,14 +18,14 @@ export default class NotificationRouter { } private buildRouteNotifications(): void { - this.router.get(`/${RESTServerRoute.REST_NOTIFICATIONS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(NotificationService.handleGetNotifications.bind(this), ServerAction.NOTIFICATIONS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_NOTIFICATIONS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(NotificationService.handleGetNotifications.bind(this), ServerAction.NOTIFICATIONS, req, res, next); }); } private buildRouteEndUserReportError(): void { - this.router.post(`/${RESTServerRoute.REST_NOTIFICATIONS_END_USER_REPORT_ERROR}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(NotificationService.handleEndUserReportError.bind(this), ServerAction.END_USER_REPORT_ERROR, req, res, next); + this.router.post(`/${RESTServerRoute.REST_NOTIFICATIONS_END_USER_REPORT_ERROR}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(NotificationService.handleEndUserReportError.bind(this), ServerAction.END_USER_REPORT_ERROR, req, res, next); }); } } diff --git a/src/server/rest/v1/router/api/OCPIEndpointRouter.ts b/src/server/rest/v1/router/api/OCPIEndpointRouter.ts index 14fd28be20..a83c19af7f 100644 --- a/src/server/rest/v1/router/api/OCPIEndpointRouter.ts +++ b/src/server/rest/v1/router/api/OCPIEndpointRouter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; import express, { NextFunction, Request, Response } from 'express'; @@ -36,133 +35,133 @@ export default class OCPIEndpointRouter { } private buildRouteOcpiEndpointCreate(): void { - this.router.post(`/${RESTServerRoute.REST_OCPI_ENDPOINTS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(OCPIEndpointService.handleCreateOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_CREATE, req, res, next); + this.router.post(`/${RESTServerRoute.REST_OCPI_ENDPOINTS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(OCPIEndpointService.handleCreateOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_CREATE, req, res, next); }); } private buildRouteOcpiEndpointPing(): void { - this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_PING}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_PING}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(OCPIEndpointService.handlePingOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_PING, req, res, next); + void RouterUtils.handleRestServerAction(OCPIEndpointService.handlePingOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_PING, req, res, next); }); } private buildRouteOcpiEndpointCheckCDRs(): void { - this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_CHECK_CDRS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_CHECK_CDRS}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(OCPIEndpointService.handleCheckCdrsEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_CHECK_CDRS, req, res, next); + void RouterUtils.handleRestServerAction(OCPIEndpointService.handleCheckCdrsEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_CHECK_CDRS, req, res, next); }); } private buildRouteOcpiEndpointCheckLocations(): void { - this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_CHECK_LOCATIONS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_CHECK_LOCATIONS}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(OCPIEndpointService.handleCheckLocationsEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_CHECK_LOCATIONS, req, res, next); + void RouterUtils.handleRestServerAction(OCPIEndpointService.handleCheckLocationsEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_CHECK_LOCATIONS, req, res, next); }); } private buildRouteOcpiEndpointCheckSessions(): void { - this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_CHECK_SESSIONS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_CHECK_SESSIONS}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(OCPIEndpointService.handleCheckSessionsEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_CHECK_SESSIONS, req, res, next); + void RouterUtils.handleRestServerAction(OCPIEndpointService.handleCheckSessionsEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_CHECK_SESSIONS, req, res, next); }); } private buildRouteOcpiEndpointPullCDRs(): void { - this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_PULL_CDRS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_PULL_CDRS}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(OCPIEndpointService.handlePullCdrsEndpoint.bind(this), ServerAction.OCPI_EMSP_GET_CDR, req, res, next); + void RouterUtils.handleRestServerAction(OCPIEndpointService.handlePullCdrsEndpoint.bind(this), ServerAction.OCPI_EMSP_GET_CDR, req, res, next); }); } private buildRouteOcpiEndpointPullLocations(): void { - this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_PULL_LOCATIONS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_PULL_LOCATIONS}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(OCPIEndpointService.handlePullLocationsEndpoint.bind(this), ServerAction.OCPI_EMSP_GET_LOCATIONS, req, res, next); + void RouterUtils.handleRestServerAction(OCPIEndpointService.handlePullLocationsEndpoint.bind(this), ServerAction.OCPI_EMSP_GET_LOCATIONS, req, res, next); }); } private buildRouteOcpiEndpointPullSessions(): void { - this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_PULL_SESSIONS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_PULL_SESSIONS}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(OCPIEndpointService.handlePullSessionsEndpoint.bind(this), ServerAction.OCPI_EMSP_GET_SESSION, req, res, next); + void RouterUtils.handleRestServerAction(OCPIEndpointService.handlePullSessionsEndpoint.bind(this), ServerAction.OCPI_EMSP_GET_SESSION, req, res, next); }); } private buildRouteOcpiEndpointPullTokens(): void { - this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_PULL_TOKENS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_PULL_TOKENS}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(OCPIEndpointService.handlePullTokensEndpoint.bind(this), ServerAction.OCPI_CPO_GET_TOKENS, req, res, next); + void RouterUtils.handleRestServerAction(OCPIEndpointService.handlePullTokensEndpoint.bind(this), ServerAction.OCPI_CPO_GET_TOKENS, req, res, next); }); } private buildRouteOcpiEndpointSendEVSEStatuses(): void { - this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_SEND_EVSE_STATUSES}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_SEND_EVSE_STATUSES}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(OCPIEndpointService.handlePushEVSEStatusesOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_SEND_EVSE_STATUSES, req, res, next); + void RouterUtils.handleRestServerAction(OCPIEndpointService.handlePushEVSEStatusesOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_SEND_EVSE_STATUSES, req, res, next); }); } private buildRouteOcpiEndpointSendTokens(): void { - this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_SEND_TOKENS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_SEND_TOKENS}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(OCPIEndpointService.handlePushTokensOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_SEND_TOKENS, req, res, next); + void RouterUtils.handleRestServerAction(OCPIEndpointService.handlePushTokensOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_SEND_TOKENS, req, res, next); }); } private buildRouteOcpiEndpointGenerateTokens(): void { - this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_GENERATE_LOCAL_TOKEN}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_GENERATE_LOCAL_TOKEN}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(OCPIEndpointService.handleGenerateLocalTokenOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_GENERATE_LOCAL_TOKEN, req, res, next); + void RouterUtils.handleRestServerAction(OCPIEndpointService.handleGenerateLocalTokenOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_GENERATE_LOCAL_TOKEN, req, res, next); }); } private buildRouteOcpiEndpoints(): void { - this.router.get(`/${RESTServerRoute.REST_OCPI_ENDPOINTS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(OCPIEndpointService.handleGetOcpiEndpoints.bind(this), ServerAction.OCPI_ENDPOINTS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_OCPI_ENDPOINTS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(OCPIEndpointService.handleGetOcpiEndpoints.bind(this), ServerAction.OCPI_ENDPOINTS, req, res, next); }); } private buildRouteOcpiEndpoint(): void { - this.router.get(`/${RESTServerRoute.REST_OCPI_ENDPOINT}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_OCPI_ENDPOINT}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(OCPIEndpointService.handleGetOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT, req, res, next); + void RouterUtils.handleRestServerAction(OCPIEndpointService.handleGetOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT, req, res, next); }); } private buildRouteOcpiEndpointUpdate(): void { - this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(OCPIEndpointService.handleUpdateOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_UPDATE, req, res, next); + void RouterUtils.handleRestServerAction(OCPIEndpointService.handleUpdateOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_UPDATE, req, res, next); }); } private buildRouteOcpiEndpointRegister(): void { - this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_REGISTER}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_REGISTER}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(OCPIEndpointService.handleRegisterOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_REGISTER, req, res, next); + void RouterUtils.handleRestServerAction(OCPIEndpointService.handleRegisterOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_REGISTER, req, res, next); }); } private buildRouteOcpiEndpointUnregister(): void { - this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_UNREGISTER}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_UNREGISTER}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(OCPIEndpointService.handleUnregisterOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_UNREGISTER, req, res, next); + void RouterUtils.handleRestServerAction(OCPIEndpointService.handleUnregisterOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_UNREGISTER, req, res, next); }); } private buildRouteOcpiEndpointCredentialsUpdate(): void { - this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_CREDENTIALS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OCPI_ENDPOINT_CREDENTIALS}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(OCPIEndpointService.handleUpdateCredentialsOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_CREDENTIALS, req, res, next); + void RouterUtils.handleRestServerAction(OCPIEndpointService.handleUpdateCredentialsOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_CREDENTIALS, req, res, next); }); } private buildRouteOcpiEndpointDelete(): void { - this.router.delete(`/${RESTServerRoute.REST_OCPI_ENDPOINT}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.delete(`/${RESTServerRoute.REST_OCPI_ENDPOINT}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(OCPIEndpointService.handleDeleteOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_DELETE, req, res, next); + void RouterUtils.handleRestServerAction(OCPIEndpointService.handleDeleteOcpiEndpoint.bind(this), ServerAction.OCPI_ENDPOINT_DELETE, req, res, next); }); } } diff --git a/src/server/rest/v1/router/api/OICPEndpointRouter.ts b/src/server/rest/v1/router/api/OICPEndpointRouter.ts index acde72cb23..a708327a49 100644 --- a/src/server/rest/v1/router/api/OICPEndpointRouter.ts +++ b/src/server/rest/v1/router/api/OICPEndpointRouter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; import express, { NextFunction, Request, Response } from 'express'; @@ -27,70 +26,70 @@ export default class OICPEndpointRouter { } private buildRouteOicpEndpointCreate(): void { - this.router.post(`/${RESTServerRoute.REST_OICP_ENDPOINTS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(OICPEndpointService.handleCreateOicpEndpoint.bind(this), ServerAction.OICP_ENDPOINT_CREATE, req, res, next); + this.router.post(`/${RESTServerRoute.REST_OICP_ENDPOINTS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(OICPEndpointService.handleCreateOicpEndpoint.bind(this), ServerAction.OICP_ENDPOINT_CREATE, req, res, next); }); } private buildRouteOicpEndpointPing(): void { - this.router.put(`/${RESTServerRoute.REST_OICP_ENDPOINT_PING}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OICP_ENDPOINT_PING}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(OICPEndpointService.handlePingOicpEndpoint.bind(this), ServerAction.OICP_ENDPOINT_PING, req, res, next); + void RouterUtils.handleRestServerAction(OICPEndpointService.handlePingOicpEndpoint.bind(this), ServerAction.OICP_ENDPOINT_PING, req, res, next); }); } private buildRouteOicpEndpointSendEvseStatuses(): void { - this.router.put(`/${RESTServerRoute.REST_OICP_ENDPOINT_SEND_EVSE_STATUSES}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OICP_ENDPOINT_SEND_EVSE_STATUSES}`, (req: Request, res: Response, next: NextFunction) => { req.params.ID = req.params.id; - await RouterUtils.handleRestServerAction(OICPEndpointService.handleSendEVSEStatusesOicpEndpoint.bind(this), ServerAction.OICP_ENDPOINT_SEND_EVSE_STATUSES, req, res, next); + void RouterUtils.handleRestServerAction(OICPEndpointService.handleSendEVSEStatusesOicpEndpoint.bind(this), ServerAction.OICP_ENDPOINT_SEND_EVSE_STATUSES, req, res, next); }); } private buildRouteOicpEndpointSendEvses(): void { - this.router.put(`/${RESTServerRoute.REST_OICP_ENDPOINT_SEND_EVSES}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OICP_ENDPOINT_SEND_EVSES}`, (req: Request, res: Response, next: NextFunction) => { req.params.ID = req.params.id; - await RouterUtils.handleRestServerAction(OICPEndpointService.handleSendEVSEsOicpEndpoint.bind(this), ServerAction.OICP_ENDPOINT_SEND_EVSES, req, res, next); + void RouterUtils.handleRestServerAction(OICPEndpointService.handleSendEVSEsOicpEndpoint.bind(this), ServerAction.OICP_ENDPOINT_SEND_EVSES, req, res, next); }); } private buildRouteOicpEndpoints(): void { - this.router.get(`/${RESTServerRoute.REST_OICP_ENDPOINTS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(OICPEndpointService.handleGetOicpEndpoints.bind(this), ServerAction.OICP_ENDPOINTS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_OICP_ENDPOINTS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(OICPEndpointService.handleGetOicpEndpoints.bind(this), ServerAction.OICP_ENDPOINTS, req, res, next); }); } private buildRouteOicpEndpoint(): void { - this.router.get(`/${RESTServerRoute.REST_OICP_ENDPOINT}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_OICP_ENDPOINT}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(OICPEndpointService.handleGetOicpEndpoint.bind(this), ServerAction.OICP_ENDPOINT, req, res, next); + void RouterUtils.handleRestServerAction(OICPEndpointService.handleGetOicpEndpoint.bind(this), ServerAction.OICP_ENDPOINT, req, res, next); }); } private buildRouteOicpEndpointUpdate(): void { - this.router.put(`/${RESTServerRoute.REST_OICP_ENDPOINT}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OICP_ENDPOINT}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(OICPEndpointService.handleUpdateOicpEndpoint.bind(this), ServerAction.OICP_ENDPOINT_UPDATE, req, res, next); + void RouterUtils.handleRestServerAction(OICPEndpointService.handleUpdateOicpEndpoint.bind(this), ServerAction.OICP_ENDPOINT_UPDATE, req, res, next); }); } private buildRouteOicpEndpointUnregister(): void { - this.router.put(`/${RESTServerRoute.REST_OICP_ENDPOINT_UNREGISTER}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OICP_ENDPOINT_UNREGISTER}`, (req: Request, res: Response, next: NextFunction) => { req.params.ID = req.params.id; - await RouterUtils.handleRestServerAction(OICPEndpointService.handleUnregisterOicpEndpoint.bind(this), ServerAction.OICP_ENDPOINT_UNREGISTER, req, res, next); + void RouterUtils.handleRestServerAction(OICPEndpointService.handleUnregisterOicpEndpoint.bind(this), ServerAction.OICP_ENDPOINT_UNREGISTER, req, res, next); }); } private buildRouteOicpEndpointRegister(): void { - this.router.put(`/${RESTServerRoute.REST_OICP_ENDPOINT_REGISTER}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_OICP_ENDPOINT_REGISTER}`, (req: Request, res: Response, next: NextFunction) => { req.params.ID = req.params.id; - await RouterUtils.handleRestServerAction(OICPEndpointService.handleRegisterOicpEndpoint.bind(this), ServerAction.OICP_ENDPOINT_REGISTER, req, res, next); + void RouterUtils.handleRestServerAction(OICPEndpointService.handleRegisterOicpEndpoint.bind(this), ServerAction.OICP_ENDPOINT_REGISTER, req, res, next); }); } private buildRouteOicpEndpointDelete(): void { - this.router.delete(`/${RESTServerRoute.REST_OICP_ENDPOINT}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.delete(`/${RESTServerRoute.REST_OICP_ENDPOINT}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(OICPEndpointService.handleDeleteOicpEndpoint.bind(this), ServerAction.OICP_ENDPOINT_DELETE, req, res, next); + void RouterUtils.handleRestServerAction(OICPEndpointService.handleDeleteOicpEndpoint.bind(this), ServerAction.OICP_ENDPOINT_DELETE, req, res, next); }); } } diff --git a/src/server/rest/v1/router/api/PricingRouter.ts b/src/server/rest/v1/router/api/PricingRouter.ts index 69380b3bda..28a7455009 100644 --- a/src/server/rest/v1/router/api/PricingRouter.ts +++ b/src/server/rest/v1/router/api/PricingRouter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; import express, { NextFunction, Request, Response } from 'express'; @@ -23,42 +22,42 @@ export default class PricingRouter { } protected buildRoutePricingDefinitions(): void { - this.router.get(`/${RESTServerRoute.REST_PRICING_DEFINITIONS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(PricingService.handleGetPricingDefinitions.bind(this), ServerAction.PRICING_DEFINITIONS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_PRICING_DEFINITIONS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(PricingService.handleGetPricingDefinitions.bind(this), ServerAction.PRICING_DEFINITIONS, req, res, next); }); } protected buildRoutePricingDefinition(): void { - this.router.get(`/${RESTServerRoute.REST_PRICING_DEFINITION}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_PRICING_DEFINITION}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(PricingService.handleGetPricingDefinition.bind(this), ServerAction.PRICING_DEFINITION, req, res, next); + void RouterUtils.handleRestServerAction(PricingService.handleGetPricingDefinition.bind(this), ServerAction.PRICING_DEFINITION, req, res, next); }); } protected buildRouteCreatePricingDefinition(): void { - this.router.post(`/${RESTServerRoute.REST_PRICING_DEFINITIONS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.post(`/${RESTServerRoute.REST_PRICING_DEFINITIONS}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(PricingService.handleCreatePricingDefinition.bind(this), ServerAction.PRICING_DEFINITION_CREATE, req, res, next); + void RouterUtils.handleRestServerAction(PricingService.handleCreatePricingDefinition.bind(this), ServerAction.PRICING_DEFINITION_CREATE, req, res, next); }); } protected buildRouteDeletePricingDefinition(): void { - this.router.delete(`/${RESTServerRoute.REST_PRICING_DEFINITION}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.delete(`/${RESTServerRoute.REST_PRICING_DEFINITION}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(PricingService.handleDeletePricingDefinition.bind(this), ServerAction.PRICING_DEFINITION_DELETE, req, res, next); + void RouterUtils.handleRestServerAction(PricingService.handleDeletePricingDefinition.bind(this), ServerAction.PRICING_DEFINITION_DELETE, req, res, next); }); } protected buildRouteUpdatePricingDefinition(): void { - this.router.put(`/${RESTServerRoute.REST_PRICING_DEFINITION}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(PricingService.handleUpdatePricingDefinition.bind(this), ServerAction.PRICING_DEFINITION_UPDATE, req, res, next); + this.router.put(`/${RESTServerRoute.REST_PRICING_DEFINITION}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(PricingService.handleUpdatePricingDefinition.bind(this), ServerAction.PRICING_DEFINITION_UPDATE, req, res, next); }); } protected buildRouteResolvePricingModel(): void { - this.router.get(`/${RESTServerRoute.REST_PRICING_MODEL_RESOLVE}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_PRICING_MODEL_RESOLVE}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(PricingService.handleResolvePricingModel.bind(this), ServerAction.PRICING_MODEL_RESOLVE, req, res, next); + void RouterUtils.handleRestServerAction(PricingService.handleResolvePricingModel.bind(this), ServerAction.PRICING_MODEL_RESOLVE, req, res, next); }); } diff --git a/src/server/rest/v1/router/api/RegistrationTokenRouter.ts b/src/server/rest/v1/router/api/RegistrationTokenRouter.ts index 37afc545e2..905e2a9dc5 100644 --- a/src/server/rest/v1/router/api/RegistrationTokenRouter.ts +++ b/src/server/rest/v1/router/api/RegistrationTokenRouter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; import express, { NextFunction, Request, Response } from 'express'; @@ -24,42 +23,42 @@ export default class RegistrationTokenRouter { } private buildRouteRegistrationTokens(): void { - this.router.get(`/${RESTServerRoute.REST_REGISTRATION_TOKENS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(RegistrationTokenService.handleGetRegistrationTokens.bind(this), ServerAction.REGISTRATION_TOKENS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_REGISTRATION_TOKENS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(RegistrationTokenService.handleGetRegistrationTokens.bind(this), ServerAction.REGISTRATION_TOKENS, req, res, next); }); } private buildRouteRegistrationToken(): void { - this.router.get(`/${RESTServerRoute.REST_REGISTRATION_TOKEN}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_REGISTRATION_TOKEN}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = sanitize(req.params.id); - await RouterUtils.handleRestServerAction(RegistrationTokenService.handleGetRegistrationToken.bind(this), ServerAction.REGISTRATION_TOKEN, req, res, next); + void RouterUtils.handleRestServerAction(RegistrationTokenService.handleGetRegistrationToken.bind(this), ServerAction.REGISTRATION_TOKEN, req, res, next); }); } private buildRouteCreateRegistrationTokens(): void { - this.router.post(`/${RESTServerRoute.REST_REGISTRATION_TOKENS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(RegistrationTokenService.handleCreateRegistrationToken.bind(this), ServerAction.REGISTRATION_TOKEN_CREATE, req, res, next); + this.router.post(`/${RESTServerRoute.REST_REGISTRATION_TOKENS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(RegistrationTokenService.handleCreateRegistrationToken.bind(this), ServerAction.REGISTRATION_TOKEN_CREATE, req, res, next); }); } private buildRouteUpdateRegistrationTokens(): void { - this.router.put(`/${RESTServerRoute.REST_REGISTRATION_TOKEN}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_REGISTRATION_TOKEN}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(RegistrationTokenService.handleUpdateRegistrationToken.bind(this), ServerAction.REGISTRATION_TOKEN_UPDATE, req, res, next); + void RouterUtils.handleRestServerAction(RegistrationTokenService.handleUpdateRegistrationToken.bind(this), ServerAction.REGISTRATION_TOKEN_UPDATE, req, res, next); }); } private buildRouteDeleteRegistrationTokens(): void { - this.router.delete(`/${RESTServerRoute.REST_REGISTRATION_TOKEN}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.delete(`/${RESTServerRoute.REST_REGISTRATION_TOKEN}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(RegistrationTokenService.handleDeleteRegistrationToken.bind(this), ServerAction.REGISTRATION_TOKEN_DELETE, req, res, next); + void RouterUtils.handleRestServerAction(RegistrationTokenService.handleDeleteRegistrationToken.bind(this), ServerAction.REGISTRATION_TOKEN_DELETE, req, res, next); }); } private buildRouteRevokeRegistrationTokens(): void { - this.router.put(`/${RESTServerRoute.REST_REGISTRATION_TOKEN_REVOKE}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_REGISTRATION_TOKEN_REVOKE}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(RegistrationTokenService.handleRevokeRegistrationToken.bind(this), ServerAction.REGISTRATION_TOKEN_REVOKE, req, res, next); + void RouterUtils.handleRestServerAction(RegistrationTokenService.handleRevokeRegistrationToken.bind(this), ServerAction.REGISTRATION_TOKEN_REVOKE, req, res, next); }); } } diff --git a/src/server/rest/v1/router/api/SettingRouter.ts b/src/server/rest/v1/router/api/SettingRouter.ts index 2cb4d05708..88bc9d5e12 100644 --- a/src/server/rest/v1/router/api/SettingRouter.ts +++ b/src/server/rest/v1/router/api/SettingRouter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; import express, { NextFunction, Request, Response } from 'express'; @@ -23,40 +22,40 @@ export default class SettingRouter { } private buildRouteSettings(): void { - this.router.get(`/${RESTServerRoute.REST_SETTINGS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_SETTINGS}`, (req: Request, res: Response, next: NextFunction) => { if (req.query.Identifier) { req.query.ID = req.query.Identifier; - await RouterUtils.handleRestServerAction(SettingService.handleGetSettingByIdentifier.bind(this), ServerAction.SETTING_BY_IDENTIFIER, req, res, next); + void RouterUtils.handleRestServerAction(SettingService.handleGetSettingByIdentifier.bind(this), ServerAction.SETTING_BY_IDENTIFIER, req, res, next); } else { - await RouterUtils.handleRestServerAction(SettingService.handleGetSettings.bind(this), ServerAction.SETTINGS, req, res, next); + void RouterUtils.handleRestServerAction(SettingService.handleGetSettings.bind(this), ServerAction.SETTINGS, req, res, next); } }); } private buildRouteSetting(): void { - this.router.get(`/${RESTServerRoute.REST_SETTING}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_SETTING}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = sanitize(req.params.id); - await RouterUtils.handleRestServerAction(SettingService.handleGetSetting.bind(this), ServerAction.SETTING, req, res, next); + void RouterUtils.handleRestServerAction(SettingService.handleGetSetting.bind(this), ServerAction.SETTING, req, res, next); }); } private buildRouteCreateSetting(): void { - this.router.post(`/${RESTServerRoute.REST_SETTINGS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(SettingService.handleCreateSetting.bind(this), ServerAction.SETTING_CREATE, req, res, next); + this.router.post(`/${RESTServerRoute.REST_SETTINGS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(SettingService.handleCreateSetting.bind(this), ServerAction.SETTING_CREATE, req, res, next); }); } private buildRouteUpdateSetting(): void { - this.router.put(`/${RESTServerRoute.REST_SETTING}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_SETTING}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(SettingService.handleUpdateSetting.bind(this), ServerAction.SETTING_UPDATE, req, res, next); + void RouterUtils.handleRestServerAction(SettingService.handleUpdateSetting.bind(this), ServerAction.SETTING_UPDATE, req, res, next); }); } private buildRouteDeleteSetting(): void { - this.router.delete(`/${RESTServerRoute.REST_SETTING}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.delete(`/${RESTServerRoute.REST_SETTING}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(SettingService.handleDeleteSetting.bind(this), ServerAction.SETTING_DELETE, req, res, next); + void RouterUtils.handleRestServerAction(SettingService.handleDeleteSetting.bind(this), ServerAction.SETTING_DELETE, req, res, next); }); } } diff --git a/src/server/rest/v1/router/api/SiteAreaRouter.ts b/src/server/rest/v1/router/api/SiteAreaRouter.ts index 3530e9c30e..465c19df2c 100644 --- a/src/server/rest/v1/router/api/SiteAreaRouter.ts +++ b/src/server/rest/v1/router/api/SiteAreaRouter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; import express, { NextFunction, Request, Response } from 'express'; @@ -27,70 +26,70 @@ export default class SiteAreaRouter { } private buildRouteSiteAreas(): void { - this.router.get(`/${RESTServerRoute.REST_SITE_AREAS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(SiteAreaService.handleGetSiteAreas.bind(this), ServerAction.SITE_AREAS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_SITE_AREAS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(SiteAreaService.handleGetSiteAreas.bind(this), ServerAction.SITE_AREAS, req, res, next); }); } private buildRouteSiteArea(): void { - this.router.get(`/${RESTServerRoute.REST_SITE_AREA}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_SITE_AREA}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(SiteAreaService.handleGetSiteArea.bind(this), ServerAction.SITE_AREA, req, res, next); + void RouterUtils.handleRestServerAction(SiteAreaService.handleGetSiteArea.bind(this), ServerAction.SITE_AREA, req, res, next); }); } private buildRouteCreateSiteArea(): void { - this.router.post(`/${RESTServerRoute.REST_SITE_AREAS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(SiteAreaService.handleCreateSiteArea.bind(this), ServerAction.SITE_AREA_CREATE, req, res, next); + this.router.post(`/${RESTServerRoute.REST_SITE_AREAS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(SiteAreaService.handleCreateSiteArea.bind(this), ServerAction.SITE_AREA_CREATE, req, res, next); }); } private buildRouteGetSiteAreaConsumption(): void { - this.router.get(`/${RESTServerRoute.REST_SITE_AREA_CONSUMPTION}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_SITE_AREA_CONSUMPTION}`, (req: Request, res: Response, next: NextFunction) => { req.query.SiteAreaID = req.params.id; - await RouterUtils.handleRestServerAction(SiteAreaService.handleGetSiteAreaConsumption.bind(this), ServerAction.SITE_AREA_CONSUMPTION, req, res, next); + void RouterUtils.handleRestServerAction(SiteAreaService.handleGetSiteAreaConsumption.bind(this), ServerAction.SITE_AREA_CONSUMPTION, req, res, next); }); } private buildRouteUpdateSiteArea(): void { - this.router.put(`/${RESTServerRoute.REST_SITE_AREA}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_SITE_AREA}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(SiteAreaService.handleUpdateSiteArea.bind(this), ServerAction.SITE_AREA_UPDATE, req, res, next); + void RouterUtils.handleRestServerAction(SiteAreaService.handleUpdateSiteArea.bind(this), ServerAction.SITE_AREA_UPDATE, req, res, next); }); } private buildRouteDeleteSiteArea(): void { - this.router.delete(`/${RESTServerRoute.REST_SITE_AREA}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.delete(`/${RESTServerRoute.REST_SITE_AREA}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(SiteAreaService.handleDeleteSiteArea.bind(this), ServerAction.SITE_AREA_DELETE, req, res, next); + void RouterUtils.handleRestServerAction(SiteAreaService.handleDeleteSiteArea.bind(this), ServerAction.SITE_AREA_DELETE, req, res, next); }); } private buildRouteAssignChargingStationsToSiteArea(): void { - this.router.put(`/${RESTServerRoute.REST_SITE_AREA_ASSIGN_CHARGING_STATIONS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_SITE_AREA_ASSIGN_CHARGING_STATIONS}`, (req: Request, res: Response, next: NextFunction) => { req.body.siteAreaID = req.params.id; - await RouterUtils.handleRestServerAction(SiteAreaService.handleAssignChargingStationsToSiteArea.bind(this), ServerAction.ADD_CHARGING_STATIONS_TO_SITE_AREA, req, res, next); + void RouterUtils.handleRestServerAction(SiteAreaService.handleAssignChargingStationsToSiteArea.bind(this), ServerAction.ADD_CHARGING_STATIONS_TO_SITE_AREA, req, res, next); }); } private buildRouteRemoveChargingStationsFromSiteArea(): void { - this.router.put(`/${RESTServerRoute.REST_SITE_AREA_REMOVE_CHARGING_STATIONS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_SITE_AREA_REMOVE_CHARGING_STATIONS}`, (req: Request, res: Response, next: NextFunction) => { req.body.siteAreaID = req.params.id; - await RouterUtils.handleRestServerAction(SiteAreaService.handleAssignChargingStationsToSiteArea.bind(this), ServerAction.REMOVE_CHARGING_STATIONS_FROM_SITE_AREA, req, res, next); + void RouterUtils.handleRestServerAction(SiteAreaService.handleAssignChargingStationsToSiteArea.bind(this), ServerAction.REMOVE_CHARGING_STATIONS_FROM_SITE_AREA, req, res, next); }); } private buildRouteAssignAssetsToSiteArea(): void { - this.router.put(`/${RESTServerRoute.REST_SITE_AREA_ASSIGN_ASSETS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_SITE_AREA_ASSIGN_ASSETS}`, (req: Request, res: Response, next: NextFunction) => { req.body.siteAreaID = req.params.id; - await RouterUtils.handleRestServerAction(SiteAreaService.handleAssignAssetsToSiteArea.bind(this), ServerAction.ADD_ASSET_TO_SITE_AREA, req, res, next); + void RouterUtils.handleRestServerAction(SiteAreaService.handleAssignAssetsToSiteArea.bind(this), ServerAction.ADD_ASSET_TO_SITE_AREA, req, res, next); }); } private buildRouteRemoveAssetsToSiteArea(): void { - this.router.put(`/${RESTServerRoute.REST_SITE_AREA_REMOVE_ASSETS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_SITE_AREA_REMOVE_ASSETS}`, (req: Request, res: Response, next: NextFunction) => { req.body.siteAreaID = req.params.id; - await RouterUtils.handleRestServerAction(SiteAreaService.handleAssignAssetsToSiteArea.bind(this), ServerAction.REMOVE_ASSET_TO_SITE_AREA, req, res, next); + void RouterUtils.handleRestServerAction(SiteAreaService.handleAssignAssetsToSiteArea.bind(this), ServerAction.REMOVE_ASSET_TO_SITE_AREA, req, res, next); }); } } diff --git a/src/server/rest/v1/router/api/SiteRouter.ts b/src/server/rest/v1/router/api/SiteRouter.ts index eb37dca818..b7ced513a7 100644 --- a/src/server/rest/v1/router/api/SiteRouter.ts +++ b/src/server/rest/v1/router/api/SiteRouter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; import express, { NextFunction, Request, Response } from 'express'; @@ -28,70 +27,70 @@ export default class SiteRouter { } private buildRouteSites(): void { - this.router.get(`/${RESTServerRoute.REST_SITES}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(SiteService.handleGetSites.bind(this), ServerAction.SITES, req, res, next); + this.router.get(`/${RESTServerRoute.REST_SITES}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(SiteService.handleGetSites.bind(this), ServerAction.SITES, req, res, next); }); } private buildRouteSite(): void { - this.router.get(`/${RESTServerRoute.REST_SITE}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_SITE}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = sanitize(req.params.id); - await RouterUtils.handleRestServerAction(SiteService.handleGetSite.bind(this), ServerAction.SITE, req, res, next); + void RouterUtils.handleRestServerAction(SiteService.handleGetSite.bind(this), ServerAction.SITE, req, res, next); }); } private buildRouteCreateSite(): void { - this.router.post(`/${RESTServerRoute.REST_SITES}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(SiteService.handleCreateSite.bind(this), ServerAction.SITE_CREATE, req, res, next); + this.router.post(`/${RESTServerRoute.REST_SITES}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(SiteService.handleCreateSite.bind(this), ServerAction.SITE_CREATE, req, res, next); }); } private buildRouteSiteAssignUsers(): void { - this.router.put(`/${RESTServerRoute.REST_SITE_ADD_USERS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_SITE_ADD_USERS}`, (req: Request, res: Response, next: NextFunction) => { req.body.siteID = req.params.id; - await RouterUtils.handleRestServerAction(SiteService.handleAssignUsersToSite.bind(this), ServerAction.ADD_USERS_TO_SITE, req, res, next); + void RouterUtils.handleRestServerAction(SiteService.handleAssignUsersToSite.bind(this), ServerAction.ADD_USERS_TO_SITE, req, res, next); }); } private buildRouteSiteUnassignUsers(): void { - this.router.put(`/${RESTServerRoute.REST_SITE_REMOVE_USERS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_SITE_REMOVE_USERS}`, (req: Request, res: Response, next: NextFunction) => { req.body.siteID = req.params.id; - await RouterUtils.handleRestServerAction(SiteService.handleAssignUsersToSite.bind(this), ServerAction.REMOVE_USERS_FROM_SITE, req, res, next); + void RouterUtils.handleRestServerAction(SiteService.handleAssignUsersToSite.bind(this), ServerAction.REMOVE_USERS_FROM_SITE, req, res, next); }); } private buildRouteSiteGetUsers(): void { - this.router.get(`/${RESTServerRoute.REST_SITE_USERS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_SITE_USERS}`, (req: Request, res: Response, next: NextFunction) => { req.query.SiteID = req.params.id; - await RouterUtils.handleRestServerAction(SiteService.handleGetUsers.bind(this), ServerAction.SITE_USERS, req, res, next); + void RouterUtils.handleRestServerAction(SiteService.handleGetUsers.bind(this), ServerAction.SITE_USERS, req, res, next); }); } private buildRouteSetSiteAdmin(): void { - this.router.put(`/${RESTServerRoute.REST_SITE_ADMIN}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_SITE_ADMIN}`, (req: Request, res: Response, next: NextFunction) => { req.body.siteID = req.params.id; - await RouterUtils.handleRestServerAction(SiteService.handleUpdateSiteUserAdmin.bind(this), ServerAction.SITE_USER_ADMIN, req, res, next); + void RouterUtils.handleRestServerAction(SiteService.handleUpdateSiteUserAdmin.bind(this), ServerAction.SITE_USER_ADMIN, req, res, next); }); } private buildRouteSetSiteOwner(): void { - this.router.put(`/${RESTServerRoute.REST_SITE_OWNER}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_SITE_OWNER}`, (req: Request, res: Response, next: NextFunction) => { req.body.siteID = req.params.id; - await RouterUtils.handleRestServerAction(SiteService.handleUpdateSiteOwner.bind(this), ServerAction.SITE_OWNER, req, res, next); + void RouterUtils.handleRestServerAction(SiteService.handleUpdateSiteOwner.bind(this), ServerAction.SITE_OWNER, req, res, next); }); } private buildRouteUpdateSite(): void { - this.router.put(`/${RESTServerRoute.REST_SITE}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_SITE}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(SiteService.handleUpdateSite.bind(this), ServerAction.SITE_UPDATE, req, res, next); + void RouterUtils.handleRestServerAction(SiteService.handleUpdateSite.bind(this), ServerAction.SITE_UPDATE, req, res, next); }); } private buildRouteDeleteSite(): void { - this.router.delete(`/${RESTServerRoute.REST_SITE}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.delete(`/${RESTServerRoute.REST_SITE}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(SiteService.handleDeleteSite.bind(this), ServerAction.SITE_DELETE, req, res, next); + void RouterUtils.handleRestServerAction(SiteService.handleDeleteSite.bind(this), ServerAction.SITE_DELETE, req, res, next); }); } } diff --git a/src/server/rest/v1/router/api/StatisticsRouter.ts b/src/server/rest/v1/router/api/StatisticsRouter.ts index cc2cf42ba4..a0abc1c806 100644 --- a/src/server/rest/v1/router/api/StatisticsRouter.ts +++ b/src/server/rest/v1/router/api/StatisticsRouter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; import express, { NextFunction, Request, Response } from 'express'; @@ -30,74 +29,74 @@ export default class StatisticsRouter { } private buildRouteStatisticsExport(): void { - this.router.get(`/${RESTServerRoute.REST_STATISTICS_EXPORT}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(StatisticService.handleExportStatistics.bind(this), ServerAction.STATISTICS_EXPORT, req, res, next); + this.router.get(`/${RESTServerRoute.REST_STATISTICS_EXPORT}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(StatisticService.handleExportStatistics.bind(this), ServerAction.STATISTICS_EXPORT, req, res, next); }); } private buildRouteChargingStationConsumptionStatistics(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_STATION_CONSUMPTION_STATISTICS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(StatisticService.handleGetChargingStationConsumptionStatistics.bind(this), ServerAction.CHARGING_STATION_CONSUMPTION_STATISTICS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_CHARGING_STATION_CONSUMPTION_STATISTICS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(StatisticService.handleGetChargingStationConsumptionStatistics.bind(this), ServerAction.CHARGING_STATION_CONSUMPTION_STATISTICS, req, res, next); }); } private buildRouteChargingStationUsageStatistics(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_STATION_USAGE_STATISTICS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(StatisticService.handleGetChargingStationUsageStatistics.bind(this), ServerAction.CHARGING_STATION_USAGE_STATISTICS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_CHARGING_STATION_USAGE_STATISTICS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(StatisticService.handleGetChargingStationUsageStatistics.bind(this), ServerAction.CHARGING_STATION_USAGE_STATISTICS, req, res, next); }); } private buildRouteChargingStationInactivityStatistics(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_STATION_INACTIVITY_STATISTICS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(StatisticService.handleGetChargingStationInactivityStatistics.bind(this), ServerAction.CHARGING_STATION_INACTIVITY_STATISTICS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_CHARGING_STATION_INACTIVITY_STATISTICS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(StatisticService.handleGetChargingStationInactivityStatistics.bind(this), ServerAction.CHARGING_STATION_INACTIVITY_STATISTICS, req, res, next); }); } private buildRouteChargingStationTransactionsStatistics(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_STATION_TRANSACTIONS_STATISTICS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(StatisticService.handleGetChargingStationTransactionsStatistics.bind(this), ServerAction.CHARGING_STATION_TRANSACTIONS_STATISTICS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_CHARGING_STATION_TRANSACTIONS_STATISTICS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(StatisticService.handleGetChargingStationTransactionsStatistics.bind(this), ServerAction.CHARGING_STATION_TRANSACTIONS_STATISTICS, req, res, next); }); } private buildRouteChargingStationPricingStatistics(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_STATION_PRICING_STATISTICS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(StatisticService.handleGetChargingStationPricingStatistics.bind(this), ServerAction.CHARGING_STATION_PRICING_STATISTICS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_CHARGING_STATION_PRICING_STATISTICS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(StatisticService.handleGetChargingStationPricingStatistics.bind(this), ServerAction.CHARGING_STATION_PRICING_STATISTICS, req, res, next); }); } private buildRouteUserConsumptionStatistics(): void { - this.router.get(`/${RESTServerRoute.REST_USER_CONSUMPTION_STATISTICS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(StatisticService.handleGetUserConsumptionStatistics.bind(this), ServerAction.USER_CONSUMPTION_STATISTICS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_USER_CONSUMPTION_STATISTICS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(StatisticService.handleGetUserConsumptionStatistics.bind(this), ServerAction.USER_CONSUMPTION_STATISTICS, req, res, next); }); } private buildRouteUserUsageStatistics(): void { - this.router.get(`/${RESTServerRoute.REST_USER_USAGE_STATISTICS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(StatisticService.handleGetUserUsageStatistics.bind(this), ServerAction.USER_USAGE_STATISTICS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_USER_USAGE_STATISTICS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(StatisticService.handleGetUserUsageStatistics.bind(this), ServerAction.USER_USAGE_STATISTICS, req, res, next); }); } private buildRouteUserInactivityStatistics(): void { - this.router.get(`/${RESTServerRoute.REST_USER_INACTIVITY_STATISTICS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(StatisticService.handleGetUserInactivityStatistics.bind(this), ServerAction.USER_INACTIVITY_STATISTICS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_USER_INACTIVITY_STATISTICS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(StatisticService.handleGetUserInactivityStatistics.bind(this), ServerAction.USER_INACTIVITY_STATISTICS, req, res, next); }); } private buildRouteUserTransactionsStatistics(): void { - this.router.get(`/${RESTServerRoute.REST_USER_TRANSACTIONS_STATISTICS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(StatisticService.handleGetUserTransactionsStatistics.bind(this), ServerAction.USER_TRANSACTIONS_STATISTICS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_USER_TRANSACTIONS_STATISTICS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(StatisticService.handleGetUserTransactionsStatistics.bind(this), ServerAction.USER_TRANSACTIONS_STATISTICS, req, res, next); }); } private buildRouteUserPricingStatistics(): void { - this.router.get(`/${RESTServerRoute.REST_USER_PRICING_STATISTICS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(StatisticService.handleGetUserPricingStatistics.bind(this), ServerAction.USER_PRICING_STATISTICS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_USER_PRICING_STATISTICS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(StatisticService.handleGetUserPricingStatistics.bind(this), ServerAction.USER_PRICING_STATISTICS, req, res, next); }); } private buildRouteTransactionsYearsStatistics(): void { - this.router.get(`/${RESTServerRoute.REST_TRANSACTION_YEARS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(TransactionService.handleGetTransactionYears.bind(this), ServerAction.TRANSACTION_YEARS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_TRANSACTION_YEARS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(TransactionService.handleGetTransactionYears.bind(this), ServerAction.TRANSACTION_YEARS, req, res, next); }); } } diff --git a/src/server/rest/v1/router/api/TagRouter.ts b/src/server/rest/v1/router/api/TagRouter.ts index a785f88eb1..cb1b063c1d 100644 --- a/src/server/rest/v1/router/api/TagRouter.ts +++ b/src/server/rest/v1/router/api/TagRouter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; import express, { NextFunction, Request, Response } from 'express'; @@ -28,81 +27,81 @@ export default class TagRouter { } private buildRouteTags(): void { - this.router.get(`/${RESTServerRoute.REST_TAGS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_TAGS}`, (req: Request, res: Response, next: NextFunction) => { if (req.query.VisualID) { - await RouterUtils.handleRestServerAction(TagService.handleGetTagByVisualID.bind(this), ServerAction.TAG_BY_VISUAL_ID, req, res, next); + void RouterUtils.handleRestServerAction(TagService.handleGetTagByVisualID.bind(this), ServerAction.TAG_BY_VISUAL_ID, req, res, next); } else { - await RouterUtils.handleRestServerAction(TagService.handleGetTags.bind(this), ServerAction.TAGS, req, res, next); + void RouterUtils.handleRestServerAction(TagService.handleGetTags.bind(this), ServerAction.TAGS, req, res, next); } }); } private buildRouteTag(): void { - this.router.get(`/${RESTServerRoute.REST_TAG}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_TAG}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(TagService.handleGetTag.bind(this), ServerAction.TAG, req, res, next); + void RouterUtils.handleRestServerAction(TagService.handleGetTag.bind(this), ServerAction.TAG, req, res, next); }); } private buildRouteCreateTag(): void { - this.router.post(`/${RESTServerRoute.REST_TAGS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.post(`/${RESTServerRoute.REST_TAGS}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(TagService.handleCreateTag.bind(this), ServerAction.TAG_CREATE, req, res, next); + void RouterUtils.handleRestServerAction(TagService.handleCreateTag.bind(this), ServerAction.TAG_CREATE, req, res, next); }); } private buildRouteDeleteTag(): void { - this.router.delete(`/${RESTServerRoute.REST_TAG}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.delete(`/${RESTServerRoute.REST_TAG}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(TagService.handleDeleteTag.bind(this), ServerAction.TAG_DELETE, req, res, next); + void RouterUtils.handleRestServerAction(TagService.handleDeleteTag.bind(this), ServerAction.TAG_DELETE, req, res, next); }); } private buildRouteDeleteTags(): void { - this.router.delete(`/${RESTServerRoute.REST_TAGS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(TagService.handleDeleteTags.bind(this), ServerAction.TAGS_DELETE, req, res, next); + this.router.delete(`/${RESTServerRoute.REST_TAGS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(TagService.handleDeleteTags.bind(this), ServerAction.TAGS_DELETE, req, res, next); }); } private buildRouteUpdateTag(): void { - this.router.put(`/${RESTServerRoute.REST_TAG}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_TAG}`, (req: Request, res: Response, next: NextFunction) => { if (req.body.id) { - await RouterUtils.handleRestServerAction(TagService.handleUpdateTag.bind(this), ServerAction.TAG_UPDATE, req, res, next); + void RouterUtils.handleRestServerAction(TagService.handleUpdateTag.bind(this), ServerAction.TAG_UPDATE, req, res, next); } else { - await RouterUtils.handleRestServerAction(TagService.handleUpdateTagByVisualID.bind(this), ServerAction.TAG_UPDATE, req, res, next); + void RouterUtils.handleRestServerAction(TagService.handleUpdateTagByVisualID.bind(this), ServerAction.TAG_UPDATE, req, res, next); } }); } private buildRouteImportTag(): void { - this.router.post(`/${RESTServerRoute.REST_TAGS_IMPORT}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(TagService.handleImportTags.bind(this), ServerAction.TAGS_IMPORT, req, res, next); + this.router.post(`/${RESTServerRoute.REST_TAGS_IMPORT}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(TagService.handleImportTags.bind(this), ServerAction.TAGS_IMPORT, req, res, next); }); } private buildRouteExportTag(): void { - this.router.get(`/${RESTServerRoute.REST_TAGS_EXPORT}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(TagService.handleExportTags.bind(this), ServerAction.TAGS_EXPORT, req, res, next); + this.router.get(`/${RESTServerRoute.REST_TAGS_EXPORT}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(TagService.handleExportTags.bind(this), ServerAction.TAGS_EXPORT, req, res, next); }); } private buildRouteAssignTag(): void { - this.router.put(`/${RESTServerRoute.REST_TAG_ASSIGN}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_TAG_ASSIGN}`, (req: Request, res: Response, next: NextFunction) => { req.body.visualID = req.params.id; - await RouterUtils.handleRestServerAction(TagService.handleAssignTag.bind(this), ServerAction.TAG_ASSIGN, req, res, next); + void RouterUtils.handleRestServerAction(TagService.handleAssignTag.bind(this), ServerAction.TAG_ASSIGN, req, res, next); }); } private buildRouteUnassignTag(): void { - this.router.put(`/${RESTServerRoute.REST_TAG_UNASSIGN}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_TAG_UNASSIGN}`, (req: Request, res: Response, next: NextFunction) => { req.body.visualID = req.params.id; - await RouterUtils.handleRestServerAction(TagService.handleUnassignTag.bind(this), ServerAction.TAG_UNASSIGN, req, res, next); + void RouterUtils.handleRestServerAction(TagService.handleUnassignTag.bind(this), ServerAction.TAG_UNASSIGN, req, res, next); }); } private buildRouteUnassignTags(): void { - this.router.put(`/${RESTServerRoute.REST_TAGS_UNASSIGN}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(TagService.handleUnassignTags.bind(this), ServerAction.TAGS_UNASSIGN, req, res, next); + this.router.put(`/${RESTServerRoute.REST_TAGS_UNASSIGN}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(TagService.handleUnassignTags.bind(this), ServerAction.TAGS_UNASSIGN, req, res, next); }); } } diff --git a/src/server/rest/v1/router/api/TenantRouter.ts b/src/server/rest/v1/router/api/TenantRouter.ts index f9530a21d6..94d83d028a 100644 --- a/src/server/rest/v1/router/api/TenantRouter.ts +++ b/src/server/rest/v1/router/api/TenantRouter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; import express, { NextFunction, Request, Response } from 'express'; @@ -23,35 +22,35 @@ export default class TenantRouter { } private buildRouteTenants(): void { - this.router.get(`/${RESTServerRoute.REST_TENANTS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(TenantService.handleGetTenants.bind(this), ServerAction.TENANTS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_TENANTS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(TenantService.handleGetTenants.bind(this), ServerAction.TENANTS, req, res, next); }); } private buildRouteTenant(): void { - this.router.get(`/${RESTServerRoute.REST_TENANT}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_TENANT}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = sanitize(req.params.id); - await RouterUtils.handleRestServerAction(TenantService.handleGetTenant.bind(this), ServerAction.TENANT, req, res, next); + void RouterUtils.handleRestServerAction(TenantService.handleGetTenant.bind(this), ServerAction.TENANT, req, res, next); }); } private buildRouteCreateTenant(): void { - this.router.post(`/${RESTServerRoute.REST_TENANTS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(TenantService.handleCreateTenant.bind(this), ServerAction.TENANT_CREATE, req, res, next); + this.router.post(`/${RESTServerRoute.REST_TENANTS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(TenantService.handleCreateTenant.bind(this), ServerAction.TENANT_CREATE, req, res, next); }); } private buildRouteUpdateTenant(): void { - this.router.put(`/${RESTServerRoute.REST_TENANT}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_TENANT}`, (req: Request, res: Response, next: NextFunction) => { req.body.id = req.params.id; - await RouterUtils.handleRestServerAction(TenantService.handleUpdateTenant.bind(this), ServerAction.TENANT_UPDATE, req, res, next); + void RouterUtils.handleRestServerAction(TenantService.handleUpdateTenant.bind(this), ServerAction.TENANT_UPDATE, req, res, next); }); } private buildRouteDeleteTenant(): void { - this.router.delete(`/${RESTServerRoute.REST_TENANT}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.delete(`/${RESTServerRoute.REST_TENANT}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(TenantService.handleDeleteTenant.bind(this), ServerAction.TENANT_DELETE, req, res, next); + void RouterUtils.handleRestServerAction(TenantService.handleDeleteTenant.bind(this), ServerAction.TENANT_DELETE, req, res, next); }); } } diff --git a/src/server/rest/v1/router/api/TransactionRouter.ts b/src/server/rest/v1/router/api/TransactionRouter.ts index 019e333edf..3fbf65a8bf 100644 --- a/src/server/rest/v1/router/api/TransactionRouter.ts +++ b/src/server/rest/v1/router/api/TransactionRouter.ts @@ -1,5 +1,4 @@ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; -/* eslint-disable @typescript-eslint/no-misused-promises */ import express, { NextFunction, Request, Response } from 'express'; import RouterUtils from '../../../../../utils/RouterUtils'; @@ -36,124 +35,124 @@ export default class TransactionRouter { } private buildRouteTransactions(): void { - this.router.get(`/${RESTServerRoute.REST_TRANSACTIONS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(TransactionService.handleGetTransactions.bind(this), ServerAction.TRANSACTIONS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_TRANSACTIONS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(TransactionService.handleGetTransactions.bind(this), ServerAction.TRANSACTIONS, req, res, next); }); } private buildRouteTransactionsInError(): void { - this.router.get(`/${RESTServerRoute.REST_TRANSACTIONS_IN_ERROR}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(TransactionService.handleGetTransactionsInError.bind(this), ServerAction.TRANSACTIONS_IN_ERROR, req, res, next); + this.router.get(`/${RESTServerRoute.REST_TRANSACTIONS_IN_ERROR}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(TransactionService.handleGetTransactionsInError.bind(this), ServerAction.TRANSACTIONS_IN_ERROR, req, res, next); }); } private buildRouteTransactionsCompleted(): void { - this.router.get(`/${RESTServerRoute.REST_TRANSACTIONS_COMPLETED}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(TransactionService.handleGetTransactionsCompleted.bind(this), ServerAction.TRANSACTIONS_COMPLETED, req, res, next); + this.router.get(`/${RESTServerRoute.REST_TRANSACTIONS_COMPLETED}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(TransactionService.handleGetTransactionsCompleted.bind(this), ServerAction.TRANSACTIONS_COMPLETED, req, res, next); }); } private buildRouteTransactionsActive(): void { - this.router.get(`/${RESTServerRoute.REST_TRANSACTIONS_ACTIVE}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(TransactionService.handleGetTransactionsActive.bind(this), ServerAction.TRANSACTIONS_ACTIVE, req, res, next); + this.router.get(`/${RESTServerRoute.REST_TRANSACTIONS_ACTIVE}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(TransactionService.handleGetTransactionsActive.bind(this), ServerAction.TRANSACTIONS_ACTIVE, req, res, next); }); } private buildRouteTransactionsGetRefund(): void { - this.router.get(`/${RESTServerRoute.REST_TRANSACTIONS_REFUND}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(TransactionService.handleGetTransactionsToRefund.bind(this), ServerAction.TRANSACTIONS_TO_REFUND, req, res, next); + this.router.get(`/${RESTServerRoute.REST_TRANSACTIONS_REFUND}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(TransactionService.handleGetTransactionsToRefund.bind(this), ServerAction.TRANSACTIONS_TO_REFUND, req, res, next); }); } private buildRouteTransaction(): void { - this.router.get(`/${RESTServerRoute.REST_TRANSACTION}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_TRANSACTION}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(TransactionService.handleGetTransaction.bind(this), ServerAction.TRANSACTION, req, res, next); + void RouterUtils.handleRestServerAction(TransactionService.handleGetTransaction.bind(this), ServerAction.TRANSACTION, req, res, next); }); } private buildRouteDeleteTransactions(): void { - this.router.delete(`/${RESTServerRoute.REST_TRANSACTIONS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(TransactionService.handleDeleteTransactions.bind(this), ServerAction.TRANSACTIONS_DELETE, req, res, next); + this.router.delete(`/${RESTServerRoute.REST_TRANSACTIONS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(TransactionService.handleDeleteTransactions.bind(this), ServerAction.TRANSACTIONS_DELETE, req, res, next); }); } private buildRouteDeleteTransaction(): void { - this.router.delete(`/${RESTServerRoute.REST_TRANSACTION}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.delete(`/${RESTServerRoute.REST_TRANSACTION}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(TransactionService.handleDeleteTransaction.bind(this), ServerAction.TRANSACTION_DELETE, req, res, next); + void RouterUtils.handleRestServerAction(TransactionService.handleDeleteTransaction.bind(this), ServerAction.TRANSACTION_DELETE, req, res, next); }); } private buildRoutePushTransactionCDR(): void { - this.router.post(`/${RESTServerRoute.REST_TRANSACTION_CDR}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.post(`/${RESTServerRoute.REST_TRANSACTION_CDR}`, (req: Request, res: Response, next: NextFunction) => { req.body.transactionId = req.params.id; - await RouterUtils.handleRestServerAction(TransactionService.handlePushTransactionCdr.bind(this), ServerAction.OCPI_CPO_PUSH_CDRS, req, res, next); + void RouterUtils.handleRestServerAction(TransactionService.handlePushTransactionCdr.bind(this), ServerAction.OCPI_CPO_PUSH_CDRS, req, res, next); }); } private buildRouteExportTransactionCDR(): void { - this.router.get(`/${RESTServerRoute.REST_TRANSACTION_CDR_EXPORT}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_TRANSACTION_CDR_EXPORT}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(TransactionService.handleExportTransactionOcpiCdr.bind(this), ServerAction.TRANSACTION_OCPI_CDR_EXPORT, req, res, next); + void RouterUtils.handleRestServerAction(TransactionService.handleExportTransactionOcpiCdr.bind(this), ServerAction.TRANSACTION_OCPI_CDR_EXPORT, req, res, next); }); } private buildRouteTransactionConsumption(): void { - this.router.get(`/${RESTServerRoute.REST_TRANSACTION_CONSUMPTIONS}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_TRANSACTION_CONSUMPTIONS}`, (req: Request, res: Response, next: NextFunction) => { req.query.TransactionId = req.params.id; - await RouterUtils.handleRestServerAction(TransactionService.handleGetTransactionConsumption.bind(this), ServerAction.TRANSACTION_CONSUMPTION, req, res, next); + void RouterUtils.handleRestServerAction(TransactionService.handleGetTransactionConsumption.bind(this), ServerAction.TRANSACTION_CONSUMPTION, req, res, next); }); } private buildRouteTransactionSoftStop(): void { - this.router.put(`/${RESTServerRoute.REST_TRANSACTION_SOFT_STOP}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_TRANSACTION_SOFT_STOP}`, (req: Request, res: Response, next: NextFunction) => { req.body.ID = req.params.id; - await RouterUtils.handleRestServerAction(TransactionService.handleTransactionSoftStop.bind(this), ServerAction.TRANSACTION_SOFT_STOP, req, res, next); + void RouterUtils.handleRestServerAction(TransactionService.handleTransactionSoftStop.bind(this), ServerAction.TRANSACTION_SOFT_STOP, req, res, next); }); } private buildRouteTransactionStop(): void { - this.router.put(`/${RESTServerRoute.REST_TRANSACTION_STOP}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_TRANSACTION_STOP}`, (req: Request, res: Response, next: NextFunction) => { req.body.ID = req.params.id; - await RouterUtils.handleRestServerAction(TransactionService.handleTransactionStop.bind(this), ServerAction.TRANSACTION_STOP, req, res, next); + void RouterUtils.handleRestServerAction(TransactionService.handleTransactionStop.bind(this), ServerAction.TRANSACTION_STOP, req, res, next); }); } private buildRouteTransactionStart(): void { - this.router.put(`/${RESTServerRoute.REST_TRANSACTION_START}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(TransactionService.handleTransactionStart.bind(this), ServerAction.TRANSACTION_START, req, res, next); + this.router.put(`/${RESTServerRoute.REST_TRANSACTION_START}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(TransactionService.handleTransactionStart.bind(this), ServerAction.TRANSACTION_START, req, res, next); }); } private buildRouteTransactionsRefund(): void { - this.router.post(`/${RESTServerRoute.REST_TRANSACTIONS_REFUND_ACTION}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.post(`/${RESTServerRoute.REST_TRANSACTIONS_REFUND_ACTION}`, (req: Request, res: Response, next: NextFunction) => { req.body.transactionsIDs = req.body.transactionIds; - await RouterUtils.handleRestServerAction(TransactionService.handleRefundTransactions.bind(this), ServerAction.TRANSACTIONS_REFUND, req, res, next); + void RouterUtils.handleRestServerAction(TransactionService.handleRefundTransactions.bind(this), ServerAction.TRANSACTIONS_REFUND, req, res, next); }); } private buildRouteTransactionsExport(): void { - this.router.get(`/${RESTServerRoute.REST_TRANSACTIONS_EXPORT}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(TransactionService.handleExportTransactions.bind(this), ServerAction.TRANSACTIONS_EXPORT, req, res, next); + this.router.get(`/${RESTServerRoute.REST_TRANSACTIONS_EXPORT}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(TransactionService.handleExportTransactions.bind(this), ServerAction.TRANSACTIONS_EXPORT, req, res, next); }); } private buildRouteSynchronizeRefundedTransactions(): void { - this.router.post(`/${RESTServerRoute.REST_TRANSACTIONS_SYNCHRONIZE_REFUNDED}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(TransactionService.handleSynchronizeRefundedTransactions.bind(this), ServerAction.SYNCHRONIZE_REFUNDED_TRANSACTIONS, req, res, next); + this.router.post(`/${RESTServerRoute.REST_TRANSACTIONS_SYNCHRONIZE_REFUNDED}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(TransactionService.handleSynchronizeRefundedTransactions.bind(this), ServerAction.SYNCHRONIZE_REFUNDED_TRANSACTIONS, req, res, next); }); } private buildRouteTransactionsRefundReports(): void { - this.router.get(`/${RESTServerRoute.REST_TRANSACTIONS_REFUND_REPORTS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(TransactionService.handleGetRefundReports.bind(this), ServerAction.TRANSACTIONS_TO_REFUND_REPORTS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_TRANSACTIONS_REFUND_REPORTS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(TransactionService.handleGetRefundReports.bind(this), ServerAction.TRANSACTIONS_TO_REFUND_REPORTS, req, res, next); }); } private buildRouteTransactionsToRefundExport(): void { - this.router.get(`/${RESTServerRoute.REST_TRANSACTIONS_REFUND_EXPORT}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(TransactionService.handleExportTransactionsToRefund.bind(this), ServerAction.TRANSACTIONS_TO_REFUND_EXPORT, req, res, next); + this.router.get(`/${RESTServerRoute.REST_TRANSACTIONS_REFUND_EXPORT}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(TransactionService.handleExportTransactionsToRefund.bind(this), ServerAction.TRANSACTIONS_TO_REFUND_EXPORT, req, res, next); }); } } diff --git a/src/server/rest/v1/router/api/UserRouter.ts b/src/server/rest/v1/router/api/UserRouter.ts index 4edae16b7d..59527c63ca 100644 --- a/src/server/rest/v1/router/api/UserRouter.ts +++ b/src/server/rest/v1/router/api/UserRouter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; import express, { NextFunction, Request, Response } from 'express'; @@ -31,97 +30,97 @@ export default class UserRouter { } private buildRouteUsers(): void { - this.router.get(`/${RESTServerRoute.REST_USERS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(UserService.handleGetUsers.bind(this), ServerAction.USERS, req, res, next); + this.router.get(`/${RESTServerRoute.REST_USERS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(UserService.handleGetUsers.bind(this), ServerAction.USERS, req, res, next); }); } private buildRouteUser(): void { - this.router.get(`/${RESTServerRoute.REST_USER}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_USER}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(UserService.handleGetUser.bind(this), ServerAction.USER, req, res, next); + void RouterUtils.handleRestServerAction(UserService.handleGetUser.bind(this), ServerAction.USER, req, res, next); }); } private buildRouteCreateUser(): void { - this.router.post(`/${RESTServerRoute.REST_USERS}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(UserService.handleCreateUser.bind(this), ServerAction.USER_CREATE, req, res, next); + this.router.post(`/${RESTServerRoute.REST_USERS}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(UserService.handleCreateUser.bind(this), ServerAction.USER_CREATE, req, res, next); }); } private buildRouteUpdateUser(): void { - this.router.put(`/${RESTServerRoute.REST_USER}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(UserService.handleUpdateUser.bind(this), ServerAction.USER_UPDATE, req, res, next); + this.router.put(`/${RESTServerRoute.REST_USER}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(UserService.handleUpdateUser.bind(this), ServerAction.USER_UPDATE, req, res, next); }); } private buildRouteDeleteUser(): void { - this.router.delete(`/${RESTServerRoute.REST_USER}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.delete(`/${RESTServerRoute.REST_USER}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(UserService.handleDeleteUser.bind(this), ServerAction.USER_DELETE, req, res, next); + void RouterUtils.handleRestServerAction(UserService.handleDeleteUser.bind(this), ServerAction.USER_DELETE, req, res, next); }); } private buildRouteUserDefaultCarTag(): void { - this.router.get(`/${RESTServerRoute.REST_USER_DEFAULT_TAG_CAR}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_USER_DEFAULT_TAG_CAR}`, (req: Request, res: Response, next: NextFunction) => { // TODO: Backward compatibility issue - remove it as soon as possible if (!req.query.UserID) { // UserID was passed as an URL parameter - URL /:id/ pattern was not resolved properly client-side! req.query.UserID = req.params.id; } - await RouterUtils.handleRestServerAction(UserService.handleGetUserDefaultTagCar.bind(this), ServerAction.USER_DEFAULT_TAG_CAR, req, res, next); + void RouterUtils.handleRestServerAction(UserService.handleGetUserDefaultTagCar.bind(this), ServerAction.USER_DEFAULT_TAG_CAR, req, res, next); }); } private buildRouteUserGetSites(): void { - this.router.get(`/${RESTServerRoute.REST_USER_SITES}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_USER_SITES}`, (req: Request, res: Response, next: NextFunction) => { req.query.UserID = req.params.id; - await RouterUtils.handleRestServerAction(UserService.handleGetSites.bind(this), ServerAction.USER_SITES, req, res, next); + void RouterUtils.handleRestServerAction(UserService.handleGetSites.bind(this), ServerAction.USER_SITES, req, res, next); }); } private buildRouteUserSiteAssign(): void { - this.router.post(`/${RESTServerRoute.REST_USER_SITES}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.post(`/${RESTServerRoute.REST_USER_SITES}`, (req: Request, res: Response, next: NextFunction) => { req.body.userID = req.params.id; - await RouterUtils.handleRestServerAction(UserService.handleAssignSitesToUser.bind(this), ServerAction.ADD_SITES_TO_USER, req, res, next); + void RouterUtils.handleRestServerAction(UserService.handleAssignSitesToUser.bind(this), ServerAction.ADD_SITES_TO_USER, req, res, next); }); } private buildRouteUserSiteUnassign(): void { - this.router.put(`/${RESTServerRoute.REST_USER_SITES}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.put(`/${RESTServerRoute.REST_USER_SITES}`, (req: Request, res: Response, next: NextFunction) => { req.body.userID = req.params.id; - await RouterUtils.handleRestServerAction(UserService.handleAssignSitesToUser.bind(this), ServerAction.REMOVE_SITES_FROM_USER, req, res, next); + void RouterUtils.handleRestServerAction(UserService.handleAssignSitesToUser.bind(this), ServerAction.REMOVE_SITES_FROM_USER, req, res, next); }); } private buildRouteUserUpdateMobileToken(): void { - this.router.put(`/${RESTServerRoute.REST_USER_UPDATE_MOBILE_TOKEN}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(UserService.handleUpdateUserMobileToken.bind(this), ServerAction.USER_UPDATE_MOBILE_TOKEN, req, res, next); + this.router.put(`/${RESTServerRoute.REST_USER_UPDATE_MOBILE_TOKEN}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(UserService.handleUpdateUserMobileToken.bind(this), ServerAction.USER_UPDATE_MOBILE_TOKEN, req, res, next); }); } private buildRouteUserGetImage(): void { - this.router.get(`/${RESTServerRoute.REST_USER_IMAGE}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_USER_IMAGE}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(UserService.handleGetUserImage.bind(this), ServerAction.USER_IMAGE, req, res, next); + void RouterUtils.handleRestServerAction(UserService.handleGetUserImage.bind(this), ServerAction.USER_IMAGE, req, res, next); }); } private buildRouteUsersInError(): void { - this.router.get(`/${RESTServerRoute.REST_USERS_IN_ERROR}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(UserService.handleGetUsersInError.bind(this), ServerAction.USERS_IN_ERROR, req, res, next); + this.router.get(`/${RESTServerRoute.REST_USERS_IN_ERROR}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(UserService.handleGetUsersInError.bind(this), ServerAction.USERS_IN_ERROR, req, res, next); }); } private buildRouteUserImport(): void { - this.router.post(`/${RESTServerRoute.REST_USERS_IMPORT}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(UserService.handleImportUsers.bind(this), ServerAction.USERS_IMPORT, req, res, next); + this.router.post(`/${RESTServerRoute.REST_USERS_IMPORT}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(UserService.handleImportUsers.bind(this), ServerAction.USERS_IMPORT, req, res, next); }); } private buildRouteUserExport(): void { - this.router.get(`/${RESTServerRoute.REST_USERS_EXPORT}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(UserService.handleExportUsers.bind(this), ServerAction.USERS_EXPORT, req, res, next); + this.router.get(`/${RESTServerRoute.REST_USERS_EXPORT}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(UserService.handleExportUsers.bind(this), ServerAction.USERS_EXPORT, req, res, next); }); } } diff --git a/src/server/rest/v1/router/auth/AuthRouter.ts b/src/server/rest/v1/router/auth/AuthRouter.ts index 0037ed806b..229511733d 100644 --- a/src/server/rest/v1/router/auth/AuthRouter.ts +++ b/src/server/rest/v1/router/auth/AuthRouter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; import express, { NextFunction, Request, Response } from 'express'; @@ -25,50 +24,50 @@ export default class AuthRouter { } protected buildRouteSignIn(): void { - this.router.post(`/${RESTServerRoute.REST_SIGNIN}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(AuthService.handleLogIn.bind(this), ServerAction.LOGIN, req, res, next); + this.router.post(`/${RESTServerRoute.REST_SIGNIN}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(AuthService.handleLogIn.bind(this), ServerAction.LOGIN, req, res, next); }); } protected buildRouteSignOn(): void { - this.router.post(`/${RESTServerRoute.REST_SIGNON}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(AuthService.handleRegisterUser.bind(this), ServerAction.REGISTER_USER, req, res, next); + this.router.post(`/${RESTServerRoute.REST_SIGNON}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(AuthService.handleRegisterUser.bind(this), ServerAction.REGISTER_USER, req, res, next); }); } protected buildRouteSignOut(): void { - this.router.get(`/${RESTServerRoute.REST_SIGNOUT}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(AuthService.handleUserLogOut.bind(this), ServerAction.LOGOUT, req, res, next); + this.router.get(`/${RESTServerRoute.REST_SIGNOUT}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(AuthService.handleUserLogOut.bind(this), ServerAction.LOGOUT, req, res, next); }); } protected buildRoutePasswordReset(): void { - this.router.post(`/${RESTServerRoute.REST_PASSWORD_RESET}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(AuthService.handleUserPasswordReset.bind(this), ServerAction.PASSWORD_RESET, req, res, next); + this.router.post(`/${RESTServerRoute.REST_PASSWORD_RESET}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(AuthService.handleUserPasswordReset.bind(this), ServerAction.PASSWORD_RESET, req, res, next); }); } protected buildRouteResendVerificationMail(): void { - this.router.post(`/${RESTServerRoute.REST_MAIL_RESEND}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(AuthService.handleResendVerificationEmail.bind(this), ServerAction.RESEND_VERIFICATION_MAIL, req, res, next); + this.router.post(`/${RESTServerRoute.REST_MAIL_RESEND}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(AuthService.handleResendVerificationEmail.bind(this), ServerAction.RESEND_VERIFICATION_MAIL, req, res, next); }); } protected buildRouteVerifyMail(): void { - this.router.get(`/${RESTServerRoute.REST_MAIL_CHECK}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(AuthService.handleVerifyEmail.bind(this), ServerAction.VERIFY_EMAIL, req, res, next); + this.router.get(`/${RESTServerRoute.REST_MAIL_CHECK}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(AuthService.handleVerifyEmail.bind(this), ServerAction.VERIFY_EMAIL, req, res, next); }); } protected buildRouteEndUserLicenseAgreement(): void { - this.router.get(`/${RESTServerRoute.REST_END_USER_LICENSE_AGREEMENT}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(AuthService.handleGetEndUserLicenseAgreement.bind(this), ServerAction.END_USER_LICENSE_AGREEMENT, req, res, next); + this.router.get(`/${RESTServerRoute.REST_END_USER_LICENSE_AGREEMENT}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(AuthService.handleGetEndUserLicenseAgreement.bind(this), ServerAction.END_USER_LICENSE_AGREEMENT, req, res, next); }); } protected buildRouteCheckEndUserLicenseAgreement(): void { - this.router.get(`/${RESTServerRoute.REST_END_USER_LICENSE_AGREEMENT_CHECK}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(AuthService.handleCheckEndUserLicenseAgreement.bind(this), ServerAction.CHECK_END_USER_LICENSE_AGREEMENT, req, res, next); + this.router.get(`/${RESTServerRoute.REST_END_USER_LICENSE_AGREEMENT_CHECK}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(AuthService.handleCheckEndUserLicenseAgreement.bind(this), ServerAction.CHECK_END_USER_LICENSE_AGREEMENT, req, res, next); }); } } diff --git a/src/server/rest/v1/router/util/UtilRouter.ts b/src/server/rest/v1/router/util/UtilRouter.ts index a9bd7235db..2718c5a001 100644 --- a/src/server/rest/v1/router/util/UtilRouter.ts +++ b/src/server/rest/v1/router/util/UtilRouter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-misused-promises */ import { RESTServerRoute, ServerAction } from '../../../../../types/Server'; import express, { NextFunction, Request, Response } from 'express'; @@ -39,50 +38,50 @@ export default class UtilRouter { } private buildRouteGetTenantLogo(): void { - this.router.get(`/${RESTServerRoute.REST_TENANT_LOGO}`, async (req: Request, res: Response, next: NextFunction) => { - await RouterUtils.handleRestServerAction(TenantService.handleGetTenantLogo.bind(this), ServerAction.TENANT_LOGO, req, res, next); + this.router.get(`/${RESTServerRoute.REST_TENANT_LOGO}`, (req: Request, res: Response, next: NextFunction) => { + void RouterUtils.handleRestServerAction(TenantService.handleGetTenantLogo.bind(this), ServerAction.TENANT_LOGO, req, res, next); }); } private buildRouteGetCarCatalogImage(): void { - this.router.get(`/${RESTServerRoute.REST_CAR_CATALOG_IMAGE}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_CAR_CATALOG_IMAGE}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(CarService.handleGetCarCatalogImage.bind(this), ServerAction.CAR_CATALOG_IMAGE, req, res, next); + void RouterUtils.handleRestServerAction(CarService.handleGetCarCatalogImage.bind(this), ServerAction.CAR_CATALOG_IMAGE, req, res, next); }); } private buildRouteGetAssetImage(): void { - this.router.get(`/${RESTServerRoute.REST_ASSET_IMAGE}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_ASSET_IMAGE}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(AssetService.handleGetAssetImage.bind(this), ServerAction.ASSET_IMAGE, req, res, next); + void RouterUtils.handleRestServerAction(AssetService.handleGetAssetImage.bind(this), ServerAction.ASSET_IMAGE, req, res, next); }); } private buildRouteGetCompanyLogo(): void { - this.router.get(`/${RESTServerRoute.REST_COMPANY_LOGO}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_COMPANY_LOGO}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(CompanyService.handleGetCompanyLogo.bind(this), ServerAction.COMPANY_LOGO, req, res, next); + void RouterUtils.handleRestServerAction(CompanyService.handleGetCompanyLogo.bind(this), ServerAction.COMPANY_LOGO, req, res, next); }); } private buildRouteGetSiteAreaImage(): void { - this.router.get(`/${RESTServerRoute.REST_SITE_AREA_IMAGE}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_SITE_AREA_IMAGE}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(SiteAreaService.handleGetSiteAreaImage.bind(this), ServerAction.SITE_AREA_IMAGE, req, res, next); + void RouterUtils.handleRestServerAction(SiteAreaService.handleGetSiteAreaImage.bind(this), ServerAction.SITE_AREA_IMAGE, req, res, next); }); } private buildRouteChargingStationDownloadFirmware(): void { - this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS_DOWNLOAD_FIRMWARE}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_CHARGING_STATIONS_DOWNLOAD_FIRMWARE}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(ChargingStationService.handleGetFirmware.bind(this), ServerAction.FIRMWARE_DOWNLOAD, req, res, next); + void RouterUtils.handleRestServerAction(ChargingStationService.handleGetFirmware.bind(this), ServerAction.FIRMWARE_DOWNLOAD, req, res, next); }); } private buildRouteGetSiteImage(): void { - this.router.get(`/${RESTServerRoute.REST_SITE_IMAGE}`, async (req: Request, res: Response, next: NextFunction) => { + this.router.get(`/${RESTServerRoute.REST_SITE_IMAGE}`, (req: Request, res: Response, next: NextFunction) => { req.query.ID = req.params.id; - await RouterUtils.handleRestServerAction(SiteService.handleGetSiteImage.bind(this), ServerAction.SITE_IMAGE, req, res, next); + void RouterUtils.handleRestServerAction(SiteService.handleGetSiteImage.bind(this), ServerAction.SITE_IMAGE, req, res, next); }); } } diff --git a/src/server/rest/v1/service/AssetService.ts b/src/server/rest/v1/service/AssetService.ts index 8d664b7cf6..86160a4769 100644 --- a/src/server/rest/v1/service/AssetService.ts +++ b/src/server/rest/v1/service/AssetService.ts @@ -246,8 +246,9 @@ export default class AssetService { // Filter const filteredRequest = AssetValidator.getInstance().validateAssetsGetReq(req.query); // Check dynamic auth - const authorizationAssetsInErrorFilter = await AuthorizationService.checkAndGetAssetsAuthorizations(req.tenant, req.user, Action.IN_ERROR, filteredRequest); - if (!authorizationAssetsInErrorFilter.authorized) { + const authorizations = await AuthorizationService.checkAndGetAssetsAuthorizations( + req.tenant, req.user, Action.IN_ERROR, filteredRequest, false); + if (!authorizations.authorized) { UtilsService.sendEmptyDataResult(res, next); return; } @@ -259,7 +260,7 @@ export default class AssetService { siteAreaIDs: (filteredRequest.SiteAreaID ? filteredRequest.SiteAreaID.split('|') : null), siteIDs: (filteredRequest.SiteID ? filteredRequest.SiteID.split('|') : null), errorType: (filteredRequest.ErrorType ? filteredRequest.ErrorType.split('|') : [AssetInErrorType.MISSING_SITE_AREA]), - ...authorizationAssetsInErrorFilter.filters + ...authorizations.filters }, { limit: filteredRequest.Limit, @@ -267,15 +268,15 @@ export default class AssetService { sort: UtilsService.httpSortFieldsToMongoDB(filteredRequest.SortFields), onlyRecordCount: filteredRequest.OnlyRecordCount }, - authorizationAssetsInErrorFilter.projectFields + authorizations.projectFields ); // Assign projected fields - if (authorizationAssetsInErrorFilter.projectFields) { - assets.projectFields = authorizationAssetsInErrorFilter.projectFields; + if (authorizations.projectFields) { + assets.projectFields = authorizations.projectFields; } // Add Auth flags await AuthorizationService.addAssetsAuthorizations( - req.tenant, req.user, assets as AssetDataResult, authorizationAssetsInErrorFilter); + req.tenant, req.user, assets as AssetDataResult, authorizations); res.json(assets); next(); } @@ -351,9 +352,9 @@ export default class AssetService { // Filter const filteredRequest = AssetValidator.getInstance().validateAssetsGetReq(req.query); // Check dynamic auth - const authorizationAssetsFilter = await AuthorizationService.checkAndGetAssetsAuthorizations( - req.tenant, req.user, Action.LIST, filteredRequest); - if (!authorizationAssetsFilter.authorized) { + const authorizations = await AuthorizationService.checkAndGetAssetsAuthorizations( + req.tenant, req.user, Action.LIST, filteredRequest, false); + if (!authorizations.authorized) { UtilsService.sendEmptyDataResult(res, next); return; } @@ -368,7 +369,7 @@ export default class AssetService { withSite: filteredRequest.WithSite, withNoSiteArea: filteredRequest.WithNoSiteArea, dynamicOnly: filteredRequest.DynamicOnly, - ...authorizationAssetsFilter.filters + ...authorizations.filters }, { limit: filteredRequest.Limit, @@ -376,15 +377,15 @@ export default class AssetService { sort: UtilsService.httpSortFieldsToMongoDB(filteredRequest.SortFields), onlyRecordCount: filteredRequest.OnlyRecordCount }, - authorizationAssetsFilter.projectFields + authorizations.projectFields ); // Assign projected fields - if (authorizationAssetsFilter.projectFields) { - assets.projectFields = authorizationAssetsFilter.projectFields; + if (authorizations.projectFields) { + assets.projectFields = authorizations.projectFields; } // Add Auth flags await AuthorizationService.addAssetsAuthorizations( - req.tenant, req.user, assets as AssetDataResult, authorizationAssetsFilter); + req.tenant, req.user, assets as AssetDataResult, authorizations); res.json(assets); next(); } @@ -395,17 +396,9 @@ export default class AssetService { Action.CREATE, Entity.ASSET, MODULE_NAME, 'handleCreateAsset'); // Check request is valid const filteredAssetRequest = AssetValidator.getInstance().validateAssetCreateReq(req.body); - UtilsService.checkIfAssetValid(filteredAssetRequest, req); // Check authorizations for current action attempt - const authorizationFilter = await AuthorizationService.checkAndGetAssetAuthorizations(req.tenant, req.user, Action.CREATE, {}, filteredAssetRequest); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - action: Action.CREATE, entity: Entity.ASSET, - module: MODULE_NAME, method: 'handleCreateAsset' - }); - } + await AuthorizationService.checkAndGetAssetAuthorizations( + req.tenant, req.user, Action.CREATE, {}, filteredAssetRequest); // Check Site Area authorization let siteArea: SiteArea = null; if (Utils.isComponentActiveFromToken(req.user, TenantComponents.ORGANIZATION) && filteredAssetRequest.siteAreaID) { @@ -443,7 +436,6 @@ export default class AssetService { Action.UPDATE, Entity.ASSET, MODULE_NAME, 'handleUpdateAsset'); // Filter const filteredRequest = AssetValidator.getInstance().validateAssetUpdateReq(req.body); - UtilsService.checkIfAssetValid(filteredRequest, req); // Check Site Area authorization let siteArea: SiteArea = null; if (Utils.isComponentActiveFromToken(req.user, TenantComponents.ORGANIZATION) && filteredRequest.siteAreaID) { diff --git a/src/server/rest/v1/service/AuthService.ts b/src/server/rest/v1/service/AuthService.ts index a5dce6eb86..560ba0a0c6 100644 --- a/src/server/rest/v1/service/AuthService.ts +++ b/src/server/rest/v1/service/AuthService.ts @@ -139,8 +139,6 @@ export default class AuthService { // Check reCaptcha await UtilsService.checkReCaptcha(tenant, action, 'handleRegisterUser', centralSystemRestConfig, filteredRequest.captcha, req.connection.remoteAddress); - // Check Mandatory field - UtilsService.checkIfUserValid(filteredRequest as User, null, req); // Check email const user = await UserStorage.getUserByEmail(tenant, filteredRequest.email); if (user) { diff --git a/src/server/rest/v1/service/AuthorizationService.ts b/src/server/rest/v1/service/AuthorizationService.ts index ee56dd3b5e..af13172b64 100644 --- a/src/server/rest/v1/service/AuthorizationService.ts +++ b/src/server/rest/v1/service/AuthorizationService.ts @@ -1,7 +1,9 @@ import { Action, AuthorizationActions, AuthorizationContext, AuthorizationFilter, Entity } from '../../../../types/Authorization'; -import { AssetDataResult, CarCatalogDataResult, CarDataResult, CompanyDataResult, LogDataResult, PricingDefinitionDataResult, RegistrationTokenDataResult, SiteAreaDataResult, SiteDataResult, TagDataResult, UserDataResult } from '../../../../types/DataResult'; +import { AssetDataResult, BillingInvoiceDataResult, BillingPaymentMethodDataResult, CarCatalogDataResult, CarDataResult, CompanyDataResult, DataResult, LogDataResult, PricingDefinitionDataResult, RegistrationTokenDataResult, SiteAreaDataResult, SiteDataResult, TagDataResult, UserDataResult } from '../../../../types/DataResult'; +import { BillingInvoice, BillingPaymentMethod } from '../../../../types/Billing'; import { Car, CarCatalog } from '../../../../types/Car'; import { HttpAssetRequest, HttpAssetsRequest } from '../../../../types/requests/HttpAssetRequest'; +import { HttpBillingInvoiceRequest, HttpBillingInvoicesRequest, HttpDeletePaymentMethod, HttpPaymentMethods, HttpSetupPaymentMethod } from '../../../../types/requests/HttpBillingRequest'; import { HttpCarCatalogRequest, HttpCarCatalogsRequest, HttpCarRequest, HttpCarsRequest } from '../../../../types/requests/HttpCarRequest'; import { HttpChargingStationRequest, HttpChargingStationsRequest } from '../../../../types/requests/HttpChargingStationRequest'; import { HttpCompaniesRequest, HttpCompanyRequest } from '../../../../types/requests/HttpCompanyRequest'; @@ -21,13 +23,14 @@ import Company from '../../../../types/Company'; import DynamicAuthorizationFactory from '../../../../authorization/DynamicAuthorizationFactory'; import { EntityData } from '../../../../types/GlobalType'; import { HTTPAuthError } from '../../../../types/HTTPError'; -import { HttpLogRequest } from '../../../../types/requests/HttpLoggingRequest'; +import { HttpLogRequest } from '../../../../types/requests/HttpLogRequest'; import { HttpRegistrationTokenRequest } from '../../../../types/requests/HttpRegistrationToken'; import { Log } from '../../../../types/Log'; import Logging from '../../../../utils/Logging'; import PricingDefinition from '../../../../types/Pricing'; import RegistrationToken from '../../../../types/RegistrationToken'; import { ServerAction } from '../../../../types/Server'; +import { Setting } from '../../../../types/Setting'; import Site from '../../../../types/Site'; import SiteArea from '../../../../types/SiteArea'; import Tag from '../../../../types/Tag'; @@ -58,8 +61,10 @@ export default class AuthorizationService { // Add Meta Data sites.metadata = authorizationFilter.metadata; // Add Authorizations - sites.canCreate = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.SITE, Action.CREATE, authorizationFilter); - sites.canListCompanies = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.COMPANY, Action.LIST, authorizationFilter); + sites.canCreate = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.SITE, Action.CREATE, authorizationFilter); + sites.canListCompanies = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.COMPANY, Action.LIST, authorizationFilter); for (const site of sites.result) { await AuthorizationService.addSiteAuthorizations(tenant, userToken, site, authorizationFilter); } @@ -91,7 +96,8 @@ export default class AuthorizationService { // Add Meta Data logs.metadata = authorizationFilter.metadata; // Add Authorizations - logs.canExport = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.LOGGING, Action.EXPORT, authorizationFilter); + logs.canExport = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.LOGGING, Action.EXPORT, authorizationFilter); for (const log of logs.result) { AuthorizationService.addLogAuthorizations(tenant, userToken, log, authorizationFilter); } @@ -102,8 +108,8 @@ export default class AuthorizationService { } public static async checkAndGetSitesAuthorizations(tenant: Tenant, userToken: UserToken, - filteredRequest: Partial): Promise { - const authorizationFilters: AuthorizationFilter = { + filteredRequest: Partial, failsWithException = true): Promise { + const authorizations: AuthorizationFilter = { filters: {}, dataSources: new Map(), projectFields: [], @@ -111,13 +117,13 @@ export default class AuthorizationService { }; // Check static & dynamic authorization await this.canPerformAuthorizationAction(tenant, userToken, Entity.SITE, Action.LIST, - authorizationFilters, filteredRequest, null, true); - return authorizationFilters; + authorizations, filteredRequest, null, failsWithException); + return authorizations; } public static async checkAndGetLoggingsAuthorizations(tenant: Tenant, userToken: UserToken, - filteredRequest: Partial): Promise { - const authorizationFilters: AuthorizationFilter = { + filteredRequest: Partial, failsWithException = true): Promise { + const authorizations: AuthorizationFilter = { filters: {}, dataSources: new Map(), projectFields: [], @@ -125,13 +131,13 @@ export default class AuthorizationService { }; // Check static & dynamic authorization await this.canPerformAuthorizationAction(tenant, userToken, Entity.LOGGING, Action.LIST, - authorizationFilters, filteredRequest, null, true); - return authorizationFilters; + authorizations, filteredRequest, null, failsWithException); + return authorizations; } public static async checkAndGetSiteUsersAuthorizations(tenant: Tenant, userToken: UserToken, - filteredRequest: Partial): Promise { - const authorizationFilters: AuthorizationFilter = { + filteredRequest: Partial, failsWithException = true): Promise { + const authorizations: AuthorizationFilter = { filters: {}, dataSources: new Map(), projectFields: [], @@ -139,13 +145,13 @@ export default class AuthorizationService { }; // Check static & dynamic authorization await this.canPerformAuthorizationAction(tenant, userToken, Entity.USERS_SITES, Action.LIST, - authorizationFilters, filteredRequest, null, true); - return authorizationFilters; + authorizations, filteredRequest, null, failsWithException); + return authorizations; } public static async checkAndGetUserSitesAuthorizations(tenant: Tenant, userToken: UserToken, filteredRequest: Partial): Promise { - const authorizationFilters: AuthorizationFilter = { + const authorizations: AuthorizationFilter = { filters: {}, dataSources: new Map(), projectFields: [ @@ -154,15 +160,15 @@ export default class AuthorizationService { authorized: userToken.role === UserRole.ADMIN, }; // Filter projected fields - authorizationFilters.projectFields = AuthorizationService.filterProjectFields(authorizationFilters.projectFields, filteredRequest.ProjectFields); + authorizations.projectFields = AuthorizationService.filterProjectFields(authorizations.projectFields, filteredRequest.ProjectFields); // Handle Sites - await AuthorizationService.checkAssignedSiteAdminsAndOwners(tenant, userToken, null, authorizationFilters); - return authorizationFilters; + await AuthorizationService.checkAssignedSiteAdminsAndOwners(tenant, userToken, null, authorizations); + return authorizations; } public static async checkAssignSiteUsersAuthorizations(tenant: Tenant, action: ServerAction, userToken: UserToken, filteredRequest: Partial): Promise { - const authorizationFilters: AuthorizationFilter = { + const authorizations: AuthorizationFilter = { filters: {}, dataSources: new Map(), projectFields: [], @@ -171,14 +177,14 @@ export default class AuthorizationService { // Check static & dynamic authorization const authAction = action === ServerAction.ADD_USERS_TO_SITE ? Action.ASSIGN : Action.UNASSIGN; await this.canPerformAuthorizationAction(tenant, userToken, Entity.USERS_SITES, authAction, - authorizationFilters, filteredRequest, null, true); - return authorizationFilters; + authorizations, filteredRequest, null, true); + return authorizations; } public static async checkAndAssignUserSitesAuthorizations( tenant: Tenant, action: ServerAction, userToken: UserToken, filteredRequest: Partial): Promise { - const authorizationFilters: AuthorizationFilter = { + const authorizations: AuthorizationFilter = { filters: {}, dataSources: new Map(), projectFields: [], @@ -187,13 +193,13 @@ export default class AuthorizationService { // Check static & dynamic authorization const authAction = action === ServerAction.ADD_USERS_TO_SITE ? Action.ASSIGN : Action.UNASSIGN; await this.canPerformAuthorizationAction(tenant, userToken, Entity.USERS_SITES, authAction, - authorizationFilters, filteredRequest, null, true); - return authorizationFilters; + authorizations, filteredRequest, null, true); + return authorizations; } public static async checkAndGetUsersInErrorAuthorizations(tenant: Tenant, userToken: UserToken, filteredRequest: Partial): Promise { - const authorizationFilters: AuthorizationFilter = { + const authorizations: AuthorizationFilter = { filters: {}, dataSources: new Map(), projectFields: [], @@ -201,17 +207,20 @@ export default class AuthorizationService { }; // Check static & dynamic authorization await this.canPerformAuthorizationAction(tenant, userToken, Entity.USER, Action.IN_ERROR, - authorizationFilters, filteredRequest, null, true); - return authorizationFilters; + authorizations, filteredRequest, null, true); + return authorizations; } public static async addUsersAuthorizations(tenant: Tenant, userToken: UserToken, users: UserDataResult, authorizationFilter: AuthorizationFilter): Promise { // Add Meta Data users.metadata = authorizationFilter.metadata; // Add Authorizations - users.canCreate = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.USER, Action.CREATE, authorizationFilter); - users.canExport = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.USER, Action.EXPORT, authorizationFilter); - users.canImport = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.USER, Action.IMPORT, authorizationFilter); + users.canCreate = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.USER, Action.CREATE, authorizationFilter); + users.canExport = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.USER, Action.EXPORT, authorizationFilter); + users.canImport = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.USER, Action.IMPORT, authorizationFilter); for (const user of users.result) { await AuthorizationService.addUserAuthorizations(tenant, userToken, user, authorizationFilter); } @@ -228,31 +237,31 @@ export default class AuthorizationService { } public static async checkAndGetUsersAuthorizations(tenant: Tenant, userToken: UserToken, - filteredRequest: Partial): Promise { - const authorizationFilters: AuthorizationFilter = { + filteredRequest: Partial, failsWithException = true): Promise { + const authorizations: AuthorizationFilter = { filters: {}, dataSources: new Map(), projectFields: [], authorized: false, }; // Check static & dynamic authorization - await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.USER, Action.LIST, - authorizationFilters, filteredRequest, null, true); - return authorizationFilters; + await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.USER, Action.LIST, authorizations, filteredRequest, null, failsWithException); + return authorizations; } public static async checkAndGetAssetsAuthorizations(tenant: Tenant, userToken: UserToken, - authAction: Action, filteredRequest?: HttpAssetsRequest): Promise { - const authorizationFilters: AuthorizationFilter = { + authAction: Action, filteredRequest?: HttpAssetsRequest, failsWithException = true): Promise { + const authorizations: AuthorizationFilter = { filters: {}, dataSources: new Map(), projectFields: [], authorized: false, }; // Check static & dynamic authorization - await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.ASSET, authAction, - authorizationFilters, filteredRequest, null, true); - return authorizationFilters; + await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.ASSET, authAction, authorizations, filteredRequest, null, failsWithException); + return authorizations; } public static async checkAndGetAssetAuthorizations(tenant: Tenant, userToken: UserToken, authAction: Action, @@ -265,9 +274,12 @@ export default class AuthorizationService { // Add Meta Data assets.metadata = authorizationFilter.metadata; // Add Authorizations - assets.canCreate = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.ASSET, Action.CREATE, authorizationFilter); - assets.canListSites = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.SITE, Action.LIST, authorizationFilter); - assets.canListSiteAreas = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.SITE_AREA, Action.LIST, authorizationFilter); + assets.canCreate = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.ASSET, Action.CREATE, authorizationFilter); + assets.canListSites = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.SITE, Action.LIST, authorizationFilter); + assets.canListSiteAreas = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.SITE_AREA, Action.LIST, authorizationFilter); for (const asset of assets.result) { await AuthorizationService.addAssetAuthorizations(tenant, userToken, asset, authorizationFilter); } @@ -275,16 +287,22 @@ export default class AuthorizationService { public static async addAssetAuthorizations(tenant: Tenant, userToken: UserToken, asset: Asset, authorizationFilter: AuthorizationFilter): Promise { asset.canRead = true; // Always true as it should be filtered upfront - asset.canDelete = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.ASSET, Action.DELETE, authorizationFilter, {}, asset); - asset.canUpdate = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.ASSET, Action.UPDATE, authorizationFilter, {}, asset); - asset.canCheckConnection = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.ASSET, Action.CHECK_CONNECTION, authorizationFilter, {}, asset); + asset.canDelete = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.ASSET, Action.DELETE, authorizationFilter, {}, asset); + asset.canUpdate = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.ASSET, Action.UPDATE, authorizationFilter, {}, asset); + asset.canCheckConnection = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.ASSET, Action.CHECK_CONNECTION, authorizationFilter, {}, asset); // Additional auth rules based on asset attributes asset.canRetrieveConsumption = asset.dynamicAsset && !asset.usesPushAPI && - await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.ASSET, Action.RETRIEVE_CONSUMPTION, authorizationFilter, {}, asset); + await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.ASSET, Action.RETRIEVE_CONSUMPTION, authorizationFilter, {}, asset); asset.canReadConsumption = asset.dynamicAsset && - await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.ASSET, Action.READ_CONSUMPTION, authorizationFilter, {}, asset); + await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.ASSET, Action.READ_CONSUMPTION, authorizationFilter, {}, asset); asset.canCreateConsumption = asset.dynamicAsset && asset.usesPushAPI && - await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.ASSET, Action.CREATE_CONSUMPTION, authorizationFilter, {}, asset); + await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.ASSET, Action.CREATE_CONSUMPTION, authorizationFilter, {}, asset); // Optimize data over the net Utils.removeCanPropertiesWithFalseValue(asset); } @@ -296,17 +314,17 @@ export default class AuthorizationService { } public static async checkAndGetTagsAuthorizations(tenant: Tenant, userToken: UserToken, - filteredRequest: Partial): Promise { - const authorizationFilters: AuthorizationFilter = { + filteredRequest: Partial, failsWithException = true): Promise { + const authorizations: AuthorizationFilter = { filters: {}, dataSources: new Map(), projectFields: [], authorized: false }; // Check static & dynamic authorization - await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.TAG, Action.LIST, - authorizationFilters, filteredRequest, null, true); - return authorizationFilters; + await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.TAG, Action.LIST, authorizations, filteredRequest, null, failsWithException); + return authorizations; } public static async checkAndGetTagAuthorizations(tenant: Tenant, userToken: UserToken, @@ -319,14 +337,22 @@ export default class AuthorizationService { // Add Meta Data tags.metadata = authorizationFilter.metadata; // Add Authorizations - tags.canCreate = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.TAG, Action.CREATE, authorizationFilter); - tags.canAssign = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.TAG, Action.ASSIGN, authorizationFilter); - tags.canDelete = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.TAG, Action.DELETE, authorizationFilter); - tags.canImport = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.TAG, Action.IMPORT, authorizationFilter); - tags.canExport = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.TAG, Action.EXPORT, authorizationFilter); - tags.canUnassign = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.TAG, Action.UNASSIGN, authorizationFilter); - tags.canListUsers = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.USER, Action.LIST, authorizationFilter); - tags.canListSources = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.SOURCE, Action.LIST, authorizationFilter); + tags.canCreate = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.TAG, Action.CREATE, authorizationFilter); + tags.canAssign = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.TAG, Action.ASSIGN, authorizationFilter); + tags.canDelete = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.TAG, Action.DELETE, authorizationFilter); + tags.canImport = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.TAG, Action.IMPORT, authorizationFilter); + tags.canExport = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.TAG, Action.EXPORT, authorizationFilter); + tags.canUnassign = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.TAG, Action.UNASSIGN, authorizationFilter); + tags.canListUsers = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.USER, Action.LIST, authorizationFilter); + tags.canListSources = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.SOURCE, Action.LIST, authorizationFilter); for (const tag of tags.result) { await AuthorizationService.addTagAuthorizations(tenant, userToken, tag, authorizationFilter); } @@ -357,17 +383,17 @@ export default class AuthorizationService { } public static async checkAndGetRegistrationTokensAuthorizations(tenant: Tenant, userToken: UserToken, - filteredRequest: Partial): Promise { - const authorizationFilters: AuthorizationFilter = { + filteredRequest: Partial, failsWithException = true): Promise { + const authorizations: AuthorizationFilter = { filters: {}, dataSources: new Map(), projectFields: [], authorized: false, }; // Check static & dynamic authorization - await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.REGISTRATION_TOKEN, Action.LIST, - authorizationFilters, filteredRequest, null, true); - return authorizationFilters; + await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.REGISTRATION_TOKEN, Action.LIST, authorizations, filteredRequest, null, failsWithException); + return authorizations; } public static async addRegistrationTokensAuthorizations(tenant: Tenant, userToken: UserToken, registrationTokens: RegistrationTokenDataResult, @@ -400,17 +426,17 @@ export default class AuthorizationService { } public static async checkAndGetCompaniesAuthorizations(tenant: Tenant, userToken: UserToken, - filteredRequest: Partial): Promise { - const authorizationFilters: AuthorizationFilter = { + filteredRequest: Partial, failsWithException = true): Promise { + const authorizations: AuthorizationFilter = { filters: {}, dataSources: new Map(), projectFields: [], authorized: false, }; // Check static & dynamic authorization - await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.COMPANY, Action.LIST, - authorizationFilters, filteredRequest, null, true); - return authorizationFilters; + await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.COMPANY, Action.LIST, authorizations, filteredRequest, null, failsWithException); + return authorizations; } public static async addCompaniesAuthorizations(tenant: Tenant, userToken: UserToken, companies: CompanyDataResult, authorizationFilter: AuthorizationFilter): Promise { @@ -441,17 +467,17 @@ export default class AuthorizationService { } public static async checkAndGetPricingDefinitionsAuthorizations(tenant: Tenant, userToken: UserToken, - filteredRequest: Partial): Promise { - const authorizationFilters: AuthorizationFilter = { + filteredRequest: Partial, failsWithException = true): Promise { + const authorizations: AuthorizationFilter = { filters: {}, dataSources: new Map(), projectFields: [], authorized: false, }; // Check static & dynamic authorization - await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.PRICING_DEFINITION, Action.LIST, - authorizationFilters, filteredRequest, null, true); - return authorizationFilters; + await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.PRICING_DEFINITION, Action.LIST, authorizations, filteredRequest, null, failsWithException); + return authorizations; } public static async addPricingDefinitionsAuthorizations(tenant: Tenant, userToken: UserToken, pricingDefinitions: PricingDefinitionDataResult, @@ -492,17 +518,17 @@ export default class AuthorizationService { } public static async checkAndGetSiteAreasAuthorizations(tenant: Tenant, userToken: UserToken, - filteredRequest: Partial): Promise { - const authorizationFilters: AuthorizationFilter = { + filteredRequest: Partial, failsWithException = true): Promise { + const authorizations: AuthorizationFilter = { filters: {}, dataSources: new Map(), projectFields: [], authorized: false, }; // Check static & dynamic authorization - await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.SITE_AREA, Action.LIST, - authorizationFilters, filteredRequest, null, true); - return authorizationFilters; + await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.SITE_AREA, Action.LIST, authorizations, filteredRequest, null, failsWithException); + return authorizations; } public static async addSiteAreasAuthorizations(tenant: Tenant, userToken: UserToken, siteAreas: SiteAreaDataResult, @@ -510,7 +536,8 @@ export default class AuthorizationService { // Add Meta Data siteAreas.metadata = authorizationFilter.metadata; // Add Authorizations - siteAreas.canCreate = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.SITE_AREA, Action.CREATE, authorizationFilter); + siteAreas.canCreate = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.SITE_AREA, Action.CREATE, authorizationFilter); for (const siteArea of siteAreas.result) { await AuthorizationService.addSiteAreaAuthorizations(tenant, userToken, siteArea, authorizationFilter); } @@ -545,7 +572,7 @@ export default class AuthorizationService { public static async checkAndGetChargingStationAuthorizations(tenant: Tenant, userToken: UserToken, filteredRequest: Partial, authAction: Action, entityData?: EntityData): Promise { - const authorizationFilters: AuthorizationFilter = { + const authorizations: AuthorizationFilter = { filters: {}, dataSources: new Map(), projectFields: [ @@ -554,33 +581,168 @@ export default class AuthorizationService { 'site.id', 'site.public', 'site.name', 'site.address', 'siteID', 'voltage', 'coordinates', 'forceInactive', 'manualConfiguration', 'firmwareUpdateStatus', 'tariffID', 'capabilities', 'endpoint', 'chargePointVendor', 'chargePointModel', 'ocppVersion', 'ocppProtocol', 'lastSeen', 'firmwareVersion', 'currentIPAddress', 'ocppStandardParameters', 'ocppVendorParameters', 'connectors', 'chargePoints', - 'createdOn', 'chargeBoxSerialNumber', 'chargePointSerialNumber', 'powerLimitUnit' + 'createdOn', 'chargeBoxSerialNumber', 'chargePointSerialNumber', 'powerLimitUnit', 'companyID' ], authorized: userToken.role === UserRole.ADMIN, }; // Filter projected fields - authorizationFilters.projectFields = AuthorizationService.filterProjectFields( - authorizationFilters.projectFields, filteredRequest.ProjectFields); + authorizations.projectFields = AuthorizationService.filterProjectFields( + authorizations.projectFields, filteredRequest.ProjectFields); // Not an Admin? if (userToken.role !== UserRole.ADMIN) { // Check assigned Sites await AuthorizationService.checkAssignedSites( - tenant, userToken, null, authorizationFilters); + tenant, userToken, null, authorizations); + } + return authorizations; + } + + public static async checkAndGetBillingAuthorizations(tenant: Tenant, userToken: UserToken, authAction: Action, entityData?: EntityData): Promise { + return AuthorizationService.checkAndGetEntityAuthorizations(tenant, Entity.BILLING, userToken, {}, {}, authAction, entityData); + } + + public static async checkAndGetTaxesAuthorizations(tenant: Tenant, userToken: UserToken, failsWithException = true): Promise { + const authorizations: AuthorizationFilter = { + filters: {}, + dataSources: new Map(), + projectFields: [], + authorized: false + }; + // Check static & dynamic authorization + await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.TAX, Action.LIST, authorizations, {}, null, failsWithException); + return authorizations; + } + + public static async checkAndGetInvoicesAuthorizations(tenant: Tenant, userToken: UserToken, + filteredRequest: Partial, failsWithException = true): Promise { + const authorizations: AuthorizationFilter = { + filters: {}, + dataSources: new Map(), + projectFields: [], + authorized: false + }; + // Check static & dynamic authorization + await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.INVOICE, Action.LIST, authorizations, filteredRequest, null, failsWithException); + return authorizations; + } + + public static async checkAndGetInvoiceAuthorizations(tenant: Tenant, userToken: UserToken, + filteredRequest: Partial, authAction: Action, entityData?: EntityData): Promise { + return AuthorizationService.checkAndGetEntityAuthorizations( + tenant, Entity.INVOICE, userToken, filteredRequest, filteredRequest.ID ? { invoiceID: filteredRequest.ID } : {}, authAction, entityData); + } + + public static async addInvoicesAuthorizations(tenant: Tenant, userToken: UserToken, billingInvoices: BillingInvoiceDataResult, + authorizationFilter: AuthorizationFilter): Promise { + // Add Meta Data + billingInvoices.metadata = authorizationFilter.metadata; + billingInvoices.canListUsers = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.USER, Action.LIST, authorizationFilter); + for (const billingInvoice of billingInvoices.result) { + await AuthorizationService.addInvoiceAuthorizations(tenant, userToken, billingInvoice, authorizationFilter); } - return authorizationFilters; } - public static async checkAndGetCarsAuthorizations(tenant: Tenant, userToken: UserToken, filteredRequest: Partial): Promise { - const authorizationFilters: AuthorizationFilter = { + public static async addInvoiceAuthorizations(tenant: Tenant, userToken: UserToken, billingInvoice: BillingInvoice, authorizationFilter: AuthorizationFilter): Promise { + billingInvoice.canRead = true; // Always true as it should be filtered upfront + billingInvoice.canDownload = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.INVOICE, Action.DOWNLOAD, authorizationFilter, billingInvoice.userID ? { UserID: billingInvoice.userID } : {}, billingInvoice); + // Optimize data over the net + Utils.removeCanPropertiesWithFalseValue(billingInvoice); + } + + public static async checkAndGetPaymentMethodsAuthorizations(tenant: Tenant, userToken: UserToken, + filteredRequest: Partial, failsWithException = true): Promise { + const authorizations: AuthorizationFilter = { filters: {}, dataSources: new Map(), projectFields: [], authorized: false }; // Check static & dynamic authorization - await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.CAR, Action.LIST, - authorizationFilters, filteredRequest, null, true); - return authorizationFilters; + await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.PAYMENT_METHOD, Action.LIST, authorizations, + filteredRequest.userID ? { UserID: filteredRequest.userID } : {}, null, failsWithException); + return authorizations; + } + + // EntityData is not usable here, the object is returned via external API call + public static async checkAndGetPaymentMethodAuthorizations(tenant: Tenant, userToken: UserToken, + filteredRequest: Partial, authAction: Action, entityData?: EntityData): Promise { + return AuthorizationService.checkAndGetEntityAuthorizations( + tenant, Entity.PAYMENT_METHOD, userToken, filteredRequest, filteredRequest.userID ? { UserID: filteredRequest.userID } : {}, authAction, entityData); + } + + public static async addPaymentMethodsAuthorizations(tenant: Tenant, userToken: UserToken, billingPaymentMethods: BillingPaymentMethodDataResult, + authorizationFilter: AuthorizationFilter, filteredRequest: Partial): Promise { + // Add Meta Data + billingPaymentMethods.metadata = authorizationFilter.metadata; + // Add Authorizations + billingPaymentMethods.canCreate = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.PAYMENT_METHOD, Action.CREATE, authorizationFilter, filteredRequest.userID ? { UserID: filteredRequest.userID } : {}); + for (const billingPaymentMethod of billingPaymentMethods.result) { + await AuthorizationService.addPaymentMethodAuthorizations(tenant, userToken, billingPaymentMethod, authorizationFilter); + } + } + + public static async addPaymentMethodAuthorizations(tenant: Tenant, userToken: UserToken, billingPaymentMethod: BillingPaymentMethod, + authorizationFilter: AuthorizationFilter): Promise { + billingPaymentMethod.canRead = true; // Always true as it should be filtered upfront + // Cannot delete default payment + billingPaymentMethod.canDelete = !billingPaymentMethod.isDefault && await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.PAYMENT_METHOD, Action.DELETE, authorizationFilter, { billingPaymentMethodID: billingPaymentMethod.id }, billingPaymentMethod); + // Remove auth flags set to false + Utils.removeCanPropertiesWithFalseValue(billingPaymentMethod); + } + + public static async checkAndGetSettingsAuthorizations(tenant: Tenant, userToken: UserToken): Promise { + const authorizations: AuthorizationFilter = { + filters: {}, + dataSources: new Map(), + projectFields: [], + authorized: false + }; + // Check static & dynamic authorization + await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.SETTING, Action.LIST, authorizations, null, null, true); + return authorizations; + } + + public static async checkAndGetSettingAuthorizations(tenant: Tenant, userToken: UserToken, authAction: Action, entityData?: EntityData): Promise { + return AuthorizationService.checkAndGetEntityAuthorizations(tenant, Entity.SETTING, userToken, {}, null, authAction, entityData); + } + + public static async addSettingsAuthorizations(tenant: Tenant, userToken: UserToken, settings: DataResult, + authorizationFilter: AuthorizationFilter): Promise { + // Add Meta Data + settings.metadata = authorizationFilter.metadata; + for (const setting of settings.result) { + await AuthorizationService.addSettingAuthorizations(tenant, userToken, setting, authorizationFilter); + } + } + + public static async addSettingAuthorizations(tenant: Tenant, userToken: UserToken, setting: Setting, authorizationFilter: AuthorizationFilter): Promise { + setting.canRead = true; // Always true as it should be filtered upfront + setting.canUpdate = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.SETTING, Action.UPDATE, authorizationFilter); + // Remove auth flags set to false + Utils.removeCanPropertiesWithFalseValue(setting); + } + + public static async checkAndGetCarsAuthorizations(tenant: Tenant, userToken: UserToken, + filteredRequest: Partial, failsWithException = true): Promise { + const authorizations: AuthorizationFilter = { + filters: {}, + dataSources: new Map(), + projectFields: [], + authorized: false + }; + // Check static & dynamic authorization + await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.CAR, Action.LIST, authorizations, filteredRequest, null, failsWithException); + return authorizations; } public static async checkAndGetCarAuthorizations(tenant: Tenant, userToken: UserToken, @@ -593,9 +755,12 @@ export default class AuthorizationService { // Add Meta Data cars.metadata = authorizationFilter.metadata; // Add Authorizations - cars.canCreate = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.CAR, Action.CREATE, authorizationFilter); - cars.canListUsers = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.USER, Action.LIST, authorizationFilter); - cars.canListCarCatalog = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.CAR_CATALOG, Action.LIST, authorizationFilter); + cars.canCreate = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.CAR, Action.CREATE, authorizationFilter); + cars.canListUsers = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.USER, Action.LIST, authorizationFilter); + cars.canListCarCatalog = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.CAR_CATALOG, Action.LIST, authorizationFilter); for (const car of cars.result) { await AuthorizationService.addCarAuthorizations(tenant, userToken, car, authorizationFilter); } @@ -603,16 +768,19 @@ export default class AuthorizationService { public static async addCarAuthorizations(tenant: Tenant, userToken: UserToken, car: Car, authorizationFilter: AuthorizationFilter): Promise { car.canRead = true; // Always true as it should be filtered upfront - car.canDelete = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.CAR, Action.DELETE, authorizationFilter, { CarID: car.id }, car); - car.canUpdate = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.CAR, Action.UPDATE, authorizationFilter, { CarID: car.id }, car); - car.canListUsers = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.USER, Action.LIST, authorizationFilter); + car.canDelete = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.CAR, Action.DELETE, authorizationFilter, { CarID: car.id }, car); + car.canUpdate = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.CAR, Action.UPDATE, authorizationFilter, { CarID: car.id }, car); + car.canListUsers = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.USER, Action.LIST, authorizationFilter); // Optimize data over the net Utils.removeCanPropertiesWithFalseValue(car); } public static async checkAndGetCarCatalogsAuthorizations(tenant: Tenant, userToken: UserToken, authAction: Action, - filteredRequest?: Partial): Promise { - const authorizationFilters: AuthorizationFilter = { + filteredRequest?: Partial, failsWithException = true): Promise { + const authorizations: AuthorizationFilter = { filters: {}, dataSources: new Map(), projectFields: [], @@ -620,8 +788,8 @@ export default class AuthorizationService { }; // Check static & dynamic authorization await this.canPerformAuthorizationAction(tenant, userToken, Entity.CAR_CATALOG, authAction, - authorizationFilters, filteredRequest, null, true); - return authorizationFilters; + authorizations, filteredRequest, null, failsWithException); + return authorizations; } public static async checkAndGetCarCatalogAuthorizations(tenant: Tenant, userToken: UserToken, filteredRequest: Partial, @@ -635,7 +803,8 @@ export default class AuthorizationService { // Add Meta Data carCatalogs.metadata = authorizationFilter.metadata; // Add Authorizations - carCatalogs.canSync = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.CAR_CATALOG, Action.SYNCHRONIZE, authorizationFilter); + carCatalogs.canSync = await AuthorizationService.canPerformAuthorizationAction( + tenant, userToken, Entity.CAR_CATALOG, Action.SYNCHRONIZE, authorizationFilter); for (const carCatalog of carCatalogs.result) { await AuthorizationService.addCarCatalogAuthorizations(tenant, userToken, carCatalog, authorizationFilter); } @@ -654,7 +823,7 @@ export default class AuthorizationService { public static async checkAndGetChargingStationsAuthorizations(tenant: Tenant, userToken: UserToken, filteredRequest?: HttpChargingStationsRequest): Promise { - const authorizationFilters: AuthorizationFilter = { + const authorizations: AuthorizationFilter = { filters: {}, dataSources: new Map(), projectFields: [], @@ -662,8 +831,8 @@ export default class AuthorizationService { }; // Check static & dynamic authorization await this.canPerformAuthorizationAction(tenant, userToken, Entity.CHARGING_STATION, Action.LIST, - authorizationFilters, filteredRequest, null, true); - return authorizationFilters; + authorizations, filteredRequest, null, true); + return authorizations; } private static async checkAssignedSites(tenant: Tenant, userToken: UserToken, @@ -867,7 +1036,7 @@ export default class AuthorizationService { private static async checkAndGetEntityAuthorizations(tenant: Tenant, authEntity: Entity, userToken: UserToken, filteredRequest: Record, entityID: Record, authAction: Action, entityData?: EntityData): Promise { - const authorizationFilters: AuthorizationFilter = { + const authorizations: AuthorizationFilter = { filters: {}, dataSources: new Map(), projectFields: [], @@ -876,8 +1045,8 @@ export default class AuthorizationService { // Check Static Auths const authorizationContext: AuthorizationContext = {}; const authResult = await Authorizations.can(userToken, authEntity, authAction, authorizationContext); - authorizationFilters.authorized = authResult.authorized; - if (!authorizationFilters.authorized) { + authorizations.authorized = authResult.authorized; + if (!authorizations.authorized) { throw new AppAuthError({ errorCode: HTTPAuthError.FORBIDDEN, user: userToken, @@ -887,8 +1056,8 @@ export default class AuthorizationService { } // Process Dynamic Filters await AuthorizationService.processDynamicFilters(tenant, userToken, authAction, authEntity, - authorizationFilters, authorizationContext, entityID, entityData); - if (!authorizationFilters.authorized) { + authorizations, authorizationContext, entityID, entityData); + if (!authorizations.authorized) { throw new AppAuthError({ errorCode: HTTPAuthError.FORBIDDEN, user: userToken, @@ -897,11 +1066,11 @@ export default class AuthorizationService { }); } // Keep the Meta Data - authorizationFilters.metadata = authResult.context.metadata; + authorizations.metadata = authResult.context.metadata; // Process Dynamic Assertions await AuthorizationService.processDynamicAsserts(tenant, userToken, authAction, authEntity, - authorizationFilters, authorizationContext, entityData); - if (!authorizationFilters.authorized) { + authorizations, authorizationContext, entityData); + if (!authorizations.authorized) { throw new AppAuthError({ errorCode: HTTPAuthError.FORBIDDEN, user: userToken, @@ -910,9 +1079,9 @@ export default class AuthorizationService { }); } // Filter projected fields - authorizationFilters.projectFields = AuthorizationService.filterProjectFields(authResult.fields, + authorizations.projectFields = AuthorizationService.filterProjectFields(authResult.fields, filteredRequest.ProjectFields); - return authorizationFilters; + return authorizations; } private static httpFilterProjectToArray(httpProjectFields: string): string[] { diff --git a/src/server/rest/v1/service/BillingService.ts b/src/server/rest/v1/service/BillingService.ts index 4b914fcf81..68519e43f1 100644 --- a/src/server/rest/v1/service/BillingService.ts +++ b/src/server/rest/v1/service/BillingService.ts @@ -1,18 +1,18 @@ import { Action, Entity } from '../../../../types/Authorization'; +import { BillingInvoiceDataResult, BillingPaymentMethodDataResult } from '../../../../types/DataResult'; import { BillingInvoiceStatus, BillingOperationResult, BillingPaymentMethod } from '../../../../types/Billing'; import { HTTPAuthError, HTTPError } from '../../../../types/HTTPError'; import { NextFunction, Request, Response } from 'express'; import AppAuthError from '../../../../exception/AppAuthError'; import AppError from '../../../../exception/AppError'; -import Authorizations from '../../../../authorization/Authorizations'; +import AuthorizationService from './AuthorizationService'; import BillingFactory from '../../../../integration/billing/BillingFactory'; import BillingSecurity from './security/BillingSecurity'; import { BillingSettings } from '../../../../types/Setting'; import BillingStorage from '../../../../storage/mongodb/BillingStorage'; import BillingValidator from '../validator/BillingValidator'; import Constants from '../../../../utils/Constants'; -import { DataResult } from '../../../../types/DataResult'; import LockingHelper from '../../../../locking/LockingHelper'; import LockingManager from '../../../../locking/LockingManager'; import Logging from '../../../../utils/Logging'; @@ -31,16 +31,9 @@ export default class BillingService { public static async handleClearBillingTestData(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise { // Check if component is active - UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING, - Action.CLEAR_BILLING_TEST_DATA, Entity.BILLING, MODULE_NAME, 'handleClearBillingTestData'); - if (!await Authorizations.canClearBillingTestData(req.user)) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - entity: Entity.BILLING, action: Action.CLEAR_BILLING_TEST_DATA, - module: MODULE_NAME, method: 'handleClearBillingTestData', - }); - } + UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING, Action.CLEAR_BILLING_TEST_DATA, Entity.BILLING, MODULE_NAME, 'handleClearBillingTestData'); + // Check dynamic auth + await AuthorizationService.checkAndGetBillingAuthorizations(req.tenant, req.user, Action.CLEAR_BILLING_TEST_DATA); const billingImpl = await BillingFactory.getBillingImpl(req.tenant); if (!billingImpl) { throw new AppError({ @@ -84,16 +77,9 @@ export default class BillingService { public static async handleCheckBillingConnection(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise { // Check if component is active - UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING, - Action.CHECK_CONNECTION, Entity.BILLING, MODULE_NAME, 'handleCheckBillingConnection'); - if (!await Authorizations.canCheckBillingConnection(req.user)) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - entity: Entity.BILLING, action: Action.CHECK_CONNECTION, - module: MODULE_NAME, method: 'handleCheckBillingConnection', - }); - } + UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING, Action.CHECK_CONNECTION, Entity.BILLING, MODULE_NAME, 'handleCheckBillingConnection'); + // Check dynamic authorization + await AuthorizationService.checkAndGetBillingAuthorizations(req.tenant, req.user, Action.CHECK_CONNECTION); const billingImpl = await BillingFactory.getBillingImpl(req.tenant); if (!billingImpl) { throw new AppError({ @@ -123,18 +109,13 @@ export default class BillingService { } public static async handleForceSynchronizeUser(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise { - const filteredRequest = BillingSecurity.filterSynchronizeUserRequest(req.body); - if (!(await Authorizations.canSynchronizeUserBilling(req.user)).authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - entity: Entity.USER, action: Action.SYNCHRONIZE_BILLING_USER, - module: MODULE_NAME, method: 'handleForceSynchronizeUser', - }); - } // Check if component is active UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING, Action.SYNCHRONIZE_BILLING_USER, Entity.USER, MODULE_NAME, 'handleForceSynchronizeUser'); + // Filter + const filteredRequest = BillingSecurity.filterSynchronizeUserRequest(req.body); + // Check dynamic authorization + await AuthorizationService.checkAndGetUserAuthorizations(req.tenant, req.user, {}, Action.SYNCHRONIZE_BILLING_USER); const billingImpl = await BillingFactory.getBillingImpl(req.tenant); if (!billingImpl) { throw new AppError({ @@ -171,17 +152,15 @@ export default class BillingService { } public static async handleGetBillingTaxes(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise { - if (!await Authorizations.canReadTaxesBilling(req.user)) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - entity: Entity.TAX, action: Action.LIST, - module: MODULE_NAME, method: 'handleGetBillingTaxes', - }); - } // Check if component is active - UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING, - Action.LIST, Entity.TAX, MODULE_NAME, 'handleGetBillingTaxes'); + UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING, Action.LIST, Entity.TAX, MODULE_NAME, 'handleGetBillingTaxes'); + // Check dynamic authorization + const authorizations = await AuthorizationService.checkAndGetTaxesAuthorizations( + req.tenant, req.user, false); + if (!authorizations.authorized) { + UtilsService.sendEmptyDataResult(res, next); + return; + } // Get Billing implementation from factory const billingImpl = await BillingFactory.getBillingImpl(req.tenant); if (!billingImpl) { @@ -201,32 +180,25 @@ export default class BillingService { public static async handleGetInvoices(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise { // Check if component is active - UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING, - Action.LIST, Entity.INVOICE, MODULE_NAME, 'handleGetInvoices'); - if (!await Authorizations.canListInvoicesBilling(req.user)) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - entity: Entity.INVOICE, action: Action.LIST, - module: MODULE_NAME, method: 'handleGetInvoices', - }); - } - // Check Users - let userProject: string[] = []; - // Temporary fix before new auth migration - if (!Authorizations.isDemo(req.user)) { - userProject = [ 'userID', 'user.id', 'user.name', 'user.firstName', 'user.email' ]; - } + UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING, Action.LIST, Entity.INVOICE, MODULE_NAME, 'handleGetInvoices'); // Filter const filteredRequest = BillingValidator.getInstance().validateBillingInvoicesGetReq(req.query); + // Check dynamic authorization + const authorizations = await AuthorizationService.checkAndGetInvoicesAuthorizations( + req.tenant, req.user, filteredRequest, false); + if (!authorizations.authorized) { + UtilsService.sendEmptyDataResult(res, next); + return; + } // Get invoices const invoices = await BillingStorage.getInvoices(req.tenant, { - userIDs: !Authorizations.isAdmin(req.user) ? [req.user.id] : (filteredRequest.UserID ? filteredRequest.UserID.split('|') : null), + userIDs: filteredRequest.UserID ? filteredRequest.UserID.split('|') : null, invoiceStatus: filteredRequest.Status ? filteredRequest.Status.split('|') as BillingInvoiceStatus[] : null, search: filteredRequest.Search ? filteredRequest.Search : null, startDateTime: filteredRequest.StartDateTime ? filteredRequest.StartDateTime : null, endDateTime: filteredRequest.EndDateTime ? filteredRequest.EndDateTime : null, + ...authorizations.filters }, { limit: filteredRequest.Limit, @@ -234,10 +206,15 @@ export default class BillingService { sort: UtilsService.httpSortFieldsToMongoDB(filteredRequest.SortFields), onlyRecordCount: filteredRequest.OnlyRecordCount }, - [ - 'id', 'number', 'status', 'amount', 'createdOn', 'currency', 'downloadable', 'sessions', - ...userProject - ]); + authorizations.projectFields + ); + // Assign projected fields + if (authorizations.projectFields) { + invoices.projectFields = authorizations.projectFields; + } + // Add Auth flags + await AuthorizationService.addInvoicesAuthorizations( + req.tenant, req.user, invoices as BillingInvoiceDataResult, authorizations); res.json(invoices); next(); } @@ -248,28 +225,8 @@ export default class BillingService { Action.LIST, Entity.INVOICE, MODULE_NAME, 'handleGetInvoice'); // Filter const filteredRequest = BillingValidator.getInstance().validateBillingInvoiceGetReq(req.query); - UtilsService.assertIdIsProvided(action, filteredRequest.ID, MODULE_NAME, 'handleGetInvoice', req.user); - // Check Users - let userProject: string[] = []; - if ((await Authorizations.canListUsers(req.user)).authorized) { - userProject = [ 'userID', 'user.id', 'user.name', 'user.firstName', 'user.email' ]; - } - // Get invoice - const invoice = await BillingStorage.getInvoice(req.tenant, filteredRequest.ID, - [ - 'id', 'number', 'status', 'amount', 'createdOn', 'currency', 'downloadable', 'sessions', - ...userProject - ]); - UtilsService.assertObjectExists(action, invoice, `Invoice ID '${filteredRequest.ID}' does not exist`, MODULE_NAME, 'handleGetInvoice', req.user); - // Check auth - if (!await Authorizations.canReadInvoiceBilling(req.user, invoice.userID)) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - entity: Entity.INVOICE, action: Action.READ, - module: MODULE_NAME, method: 'handleGetInvoice', - }); - } + // Check and get invoice + const invoice = await UtilsService.checkAndGetInvoiceAuthorization(req.tenant, req.user, filteredRequest.ID, Action.READ, action, null, {}, true); res.json(invoice); next(); } @@ -280,14 +237,8 @@ export default class BillingService { Action.BILLING_SETUP_PAYMENT_METHOD, Entity.BILLING, MODULE_NAME, 'handleSetupSetupPaymentMethod'); // Filter const filteredRequest = BillingValidator.getInstance().validateBillingSetupUserPaymentMethodReq(req.body); - if (!await Authorizations.canCreatePaymentMethod(req.user, filteredRequest.userID)) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - action: Action.CREATE, entity: Entity.PAYMENT_METHOD, - module: MODULE_NAME, method: 'handleBillingSetupPaymentMethod' - }); - } + // Dynamic auth + await AuthorizationService.checkAndGetPaymentMethodAuthorizations(req.tenant, req.user, filteredRequest, Action.CREATE); // Get the billing impl const billingImpl = await BillingFactory.getBillingImpl(req.tenant); if (!billingImpl) { @@ -299,10 +250,8 @@ export default class BillingService { user: req.user }); } - // Get user - ACHTUNG user !== req.user - const user: User = await UserStorage.getUser(req.tenant, filteredRequest.userID); - UtilsService.assertObjectExists(action, user, `User ID '${filteredRequest.userID}' does not exist`, - MODULE_NAME, 'handleSetupPaymentMethod', req.user); + // Check and get user for whom we wish to update the payment method + const user: User = await UtilsService.checkAndGetUserAuthorization(req.tenant, req.user, filteredRequest.userID, Action.READ, action); // Invoke the billing implementation const paymentMethodId: string = filteredRequest.paymentMethodId; const operationResult: BillingOperationResult = await billingImpl.setupPaymentMethod(user, paymentMethodId); @@ -319,13 +268,11 @@ export default class BillingService { // Check if component is active UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING, Action.BILLING_PAYMENT_METHODS, Entity.BILLING, MODULE_NAME, 'handleBillingGetPaymentMethods'); - if (!await Authorizations.canListPaymentMethod(req.user)) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - action: Action.CREATE, entity: Entity.PAYMENT_METHOD, - module: MODULE_NAME, method: 'handleBillingGetPaymentMethods' - }); + const authorizations = await AuthorizationService.checkAndGetPaymentMethodsAuthorizations( + req.tenant, req.user,filteredRequest, false); + if (!authorizations.authorized) { + UtilsService.sendEmptyDataResult(res, next); + return; } // Get the billing impl const billingImpl = await BillingFactory.getBillingImpl(req.tenant); @@ -339,9 +286,7 @@ export default class BillingService { }); } // Get user - ACHTUNG user !== req.user - const user: User = await UserStorage.getUser(req.tenant, filteredRequest.userID); - UtilsService.assertObjectExists(action, user, `User ID '${filteredRequest.userID}' does not exist`, - MODULE_NAME, 'handleBillingGetPaymentMethods', req.user); + const user: User = await UtilsService.checkAndGetUserAuthorization(req.tenant, req.user, filteredRequest.userID, Action.READ, action); // Invoke the billing implementation const paymentMethods: BillingPaymentMethod[] = await billingImpl.getPaymentMethods(user); await Logging.logInfo({ @@ -351,10 +296,11 @@ export default class BillingService { module: MODULE_NAME, method: 'getPaymentMethods', message: `Number of payment methods: ${paymentMethods?.length}` }); - const dataResult: DataResult = { + const dataResult: BillingPaymentMethodDataResult = { count: paymentMethods.length, result: paymentMethods }; + await AuthorizationService.addPaymentMethodsAuthorizations(req.tenant, req.user, dataResult, authorizations, filteredRequest); res.json(dataResult); next(); } @@ -365,14 +311,8 @@ export default class BillingService { // Check if component is active UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING, Action.BILLING_PAYMENT_METHODS, Entity.BILLING, MODULE_NAME, 'handleBillingDeletePaymentMethod'); - if (!await Authorizations.canDeletePaymentMethod(req.user)) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - action: Action.DELETE, entity: Entity.PAYMENT_METHOD, - module: MODULE_NAME, method: 'handleBillingDeletePaymentMethod' - }); - } + // Dynamic auth + await AuthorizationService.checkAndGetPaymentMethodAuthorizations(req.tenant, req.user, filteredRequest, Action.DELETE); // Get the billing impl const billingImpl = await BillingFactory.getBillingImpl(req.tenant); if (!billingImpl) { @@ -384,9 +324,8 @@ export default class BillingService { user: req.user }); } - const userID = filteredRequest.userID; - const user: User = await UserStorage.getUser(req.tenant, userID); - UtilsService.assertObjectExists(action, user, `User ID '${userID}' does not exist`, + const user: User = await UtilsService.checkAndGetUserAuthorization(req.tenant, req.user, filteredRequest.userID, Action.READ, action); + UtilsService.assertObjectExists(action, user, `User ID '${filteredRequest.userID}' does not exist`, MODULE_NAME, 'handleBillingDeletePaymentMethod', req.user); // Invoke the billing implementation const operationResult: BillingOperationResult = await billingImpl.deletePaymentMethod(user, filteredRequest.paymentMethodId); @@ -411,15 +350,8 @@ export default class BillingService { const billingInvoice = await BillingStorage.getInvoice(req.tenant, filteredRequest.ID); UtilsService.assertObjectExists(action, billingInvoice, `Invoice ID '${filteredRequest.ID}' does not exist`, MODULE_NAME, 'handleDownloadInvoice', req.user); - // Check Auth - if (!await Authorizations.canDownloadInvoiceBilling(req.user, billingInvoice.userID)) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - entity: Entity.INVOICE, action: Action.DOWNLOAD, - module: MODULE_NAME, method: 'handleDownloadInvoice', - }); - } + // Check and get authorizations + await UtilsService.checkAndGetInvoiceAuthorization(req.tenant, req.user, filteredRequest.ID, Action.DOWNLOAD, action, null, {}, true); // Get the billing impl const billingImpl = await BillingFactory.getBillingImpl(req.tenant); if (!billingImpl) { @@ -452,17 +384,8 @@ export default class BillingService { // Check if component is active UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING, Action.READ, Entity.SETTING, MODULE_NAME, 'handleGetBillingSetting'); - // Check auth - if (!await Authorizations.canReadBillingSetting(req.user)) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - action: Action.READ, entity: Entity.SETTING, - module: MODULE_NAME, method: 'handleGetBillingSetting', - }); - } - const billingSettings: BillingSettings = await SettingStorage.getBillingSetting(req.tenant); - UtilsService.assertObjectExists(action, billingSettings, 'Failed to load billing settings', MODULE_NAME, 'handleGetBillingSetting', req.user); + const billingSettings: BillingSettings = await UtilsService.checkAndGetBillingSettingAuthorization(req.tenant, req.user, null, Action.READ, action); + // Process sensitive data UtilsService.hashSensitiveData(req.tenant.id, billingSettings); res.json(billingSettings); next(); @@ -472,19 +395,10 @@ export default class BillingService { // Check if component is active UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING, Action.UPDATE, Entity.SETTING, MODULE_NAME, 'handleUpdateBillingSetting'); - // Check auth - if (!await Authorizations.canUpdateBillingSetting(req.user)) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - action: Action.UPDATE, entity: Entity.SETTING, - module: MODULE_NAME, method: 'handleUpdateBillingSetting', - }); - } const newBillingProperties = BillingValidator.getInstance().validateBillingSettingUpdateReq({ ...req.params, ...req.body }); - // Load previous settings - const billingSettings = await SettingStorage.getBillingSetting(req.tenant); - UtilsService.assertObjectExists(action, billingSettings, 'Failed to load billing settings', MODULE_NAME, 'handleUpdateBillingSetting', req.user); + // Check and get previous settings that we want to update + const billingSettings: BillingSettings = await UtilsService.checkAndGetBillingSettingAuthorization(req.tenant, req.user, null, Action.UPDATE, action); + // Process sensitive data await UtilsService.processSensitiveData(req.tenant, billingSettings, newBillingProperties); // Billing properties to preserve const { usersLastSynchronizedOn } = billingSettings.billing; diff --git a/src/server/rest/v1/service/CarService.ts b/src/server/rest/v1/service/CarService.ts index 05ab96395e..ce38795f83 100644 --- a/src/server/rest/v1/service/CarService.ts +++ b/src/server/rest/v1/service/CarService.ts @@ -35,8 +35,9 @@ export default class CarService { // Filter const filteredRequest = CarValidator.getInstance().validateCarCatalogsGetReq(req.query); // Check auth - const authorizationCarCatalogsFilter = await AuthorizationService.checkAndGetCarCatalogsAuthorizations(req.tenant, req.user, Action.LIST, filteredRequest); - if (!authorizationCarCatalogsFilter.authorized) { + const authorizations = await AuthorizationService.checkAndGetCarCatalogsAuthorizations( + req.tenant, req.user, Action.LIST, filteredRequest, false); + if (!authorizations.authorized) { UtilsService.sendEmptyDataResult(res, next); return; } @@ -46,7 +47,7 @@ export default class CarService { search: filteredRequest.Search, carMaker: filteredRequest.CarMaker ? filteredRequest.CarMaker.split('|') : null, withImage: true, - ...authorizationCarCatalogsFilter.filters + ...authorizations.filters }, { limit: filteredRequest.Limit, @@ -54,15 +55,15 @@ export default class CarService { sort: UtilsService.httpSortFieldsToMongoDB(filteredRequest.SortFields), onlyRecordCount: filteredRequest.OnlyRecordCount }, - authorizationCarCatalogsFilter.projectFields + authorizations.projectFields ); // Assign projected fields - if (authorizationCarCatalogsFilter.projectFields) { - carCatalogs.projectFields = authorizationCarCatalogsFilter.projectFields; + if (authorizations.projectFields) { + carCatalogs.projectFields = authorizations.projectFields; } // Add Auth flags await AuthorizationService.addCarCatalogsAuthorizationActions(req.tenant, req.user, carCatalogs as CarCatalogDataResult, - authorizationCarCatalogsFilter); + authorizations); res.json(carCatalogs); next(); } @@ -114,17 +115,8 @@ export default class CarService { // Filter const filteredRequest = CarValidator.getInstance().validateCarCatalogImagesGetReq(req.query); // Check dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetCarCatalogAuthorizations( + await AuthorizationService.checkAndGetCarCatalogAuthorizations( req.tenant, req.user, { ID: filteredRequest.ID }, Action.READ); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - action: Action.READ, entity: Entity.CAR_CATALOG, - module: MODULE_NAME, method: 'handleGetCarCatalogImages', - value: filteredRequest.ID.toString() - }); - } // Get the car const carCatalogImages = await CarStorage.getCarCatalogImages( filteredRequest.ID, @@ -141,15 +133,8 @@ export default class CarService { Action.SYNCHRONIZE, Entity.CAR_CATALOG, MODULE_NAME, 'handleSynchronizeCarCatalogs'); } // Check auth - const authorizationFilter = await AuthorizationService.checkAndGetCarCatalogsAuthorizations(req.tenant, req.user, Action.SYNCHRONIZE); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - action: Action.SYNCHRONIZE, entity: Entity.CAR_CATALOG, - module: MODULE_NAME, method: 'handleSynchronizeCarCatalogs' - }); - } + await AuthorizationService.checkAndGetCarCatalogsAuthorizations( + req.tenant, req.user, Action.SYNCHRONIZE); // Get the lock const syncCarCatalogsLock = await LockingHelper.acquireSyncCarCatalogsLock(Constants.DEFAULT_TENANT_ID); if (!syncCarCatalogsLock) { @@ -188,14 +173,11 @@ export default class CarService { // Filter const filteredRequest = CarValidator.getInstance().validateCarMakersGetReq(req.query); // Check auth - const authorizationCarCatalogsFilter = await AuthorizationService.checkAndGetCarCatalogsAuthorizations(req.tenant, req.user, Action.LIST, filteredRequest); - if (!authorizationCarCatalogsFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - action: Action.READ, entity: Entity.CAR_CATALOG, - module: MODULE_NAME, method: 'handleGetCarMakers' - }); + const authorizations = await AuthorizationService.checkAndGetCarCatalogsAuthorizations( + req.tenant, req.user, Action.LIST, filteredRequest, false); + if (!authorizations.authorized) { + UtilsService.sendEmptyDataResult(res, next); + return; } // Get car makers const carMakers = await CarStorage.getCarMakers({ search: filteredRequest.Search }, [ 'carMaker' ]); @@ -209,7 +191,6 @@ export default class CarService { Action.CREATE, Entity.CAR, MODULE_NAME, 'handleCreateCar'); // Filter const filteredRequest = CarValidator.getInstance().validateCarCreateReq(req.body); - UtilsService.checkIfCarValid(filteredRequest, req); // Check auth await AuthorizationService.checkAndGetCarAuthorizations( req.tenant,req.user, {}, Action.CREATE, filteredRequest as Car); @@ -279,7 +260,6 @@ export default class CarService { Action.UPDATE, Entity.CAR, MODULE_NAME, 'handleUpdateCar'); // Filter const filteredRequest = CarValidator.getInstance().validateCarUpdateReq(req.body); - UtilsService.checkIfCarValid(filteredRequest, req); // Check and Get Car const car = await UtilsService.checkAndGetCarAuthorization( req.tenant, req.user, filteredRequest.id, Action.UPDATE, action, filteredRequest as Car); @@ -362,9 +342,9 @@ export default class CarService { // Filter const filteredRequest = CarValidator.getInstance().validateCarsGetReq(req.query); // Check auth - const authorizationCarsFilter = await AuthorizationService.checkAndGetCarsAuthorizations( - req.tenant, req.user, filteredRequest); - if (!authorizationCarsFilter.authorized) { + const authorizations = await AuthorizationService.checkAndGetCarsAuthorizations( + req.tenant, req.user, filteredRequest, false); + if (!authorizations.authorized) { UtilsService.sendEmptyDataResult(res, next); return; } @@ -375,7 +355,7 @@ export default class CarService { carMakers: filteredRequest.CarMaker ? filteredRequest.CarMaker.split('|') : null, withUser: filteredRequest.WithUser, userIDs: filteredRequest.UserID ? filteredRequest.UserID.split('|') : null, - ...authorizationCarsFilter.filters + ...authorizations.filters }, { limit: filteredRequest.Limit, @@ -383,15 +363,15 @@ export default class CarService { sort: UtilsService.httpSortFieldsToMongoDB(filteredRequest.SortFields), onlyRecordCount: filteredRequest.OnlyRecordCount }, - authorizationCarsFilter.projectFields + authorizations.projectFields ); // Assign projected fields - if (authorizationCarsFilter.projectFields) { - cars.projectFields = authorizationCarsFilter.projectFields; + if (authorizations.projectFields) { + cars.projectFields = authorizations.projectFields; } // Add Auth flags await AuthorizationService.addCarsAuthorizations( - req.tenant, req.user, cars as CarDataResult, authorizationCarsFilter); + req.tenant, req.user, cars as CarDataResult, authorizations); res.json(cars); next(); } diff --git a/src/server/rest/v1/service/ChargingStationService.ts b/src/server/rest/v1/service/ChargingStationService.ts index a53d4e385e..ddeab33ae1 100644 --- a/src/server/rest/v1/service/ChargingStationService.ts +++ b/src/server/rest/v1/service/ChargingStationService.ts @@ -499,7 +499,6 @@ export default class ChargingStationService { Action.UPDATE, Entity.SITE_AREA, MODULE_NAME, 'handleTriggerSmartCharging'); // Filter const filteredRequest = ChargingStationValidator.getInstance().validateSmartChargingTriggerReq(req.query); - UtilsService.assertIdIsProvided(action, filteredRequest.SiteAreaID, MODULE_NAME, 'handleTriggerSmartCharging', req.user); // Get Site Area const siteArea = await SiteAreaStorage.getSiteArea(req.tenant, filteredRequest.SiteAreaID); UtilsService.assertObjectExists(action, siteArea, `Site Area ID '${filteredRequest.SiteAreaID}' does not exist`, @@ -565,10 +564,6 @@ export default class ChargingStationService { chargingStationID: filteredRequest.ChargingStationID, }); } - // Check ChargeBoxID - UtilsService.assertIdIsProvided(action, filteredRequest.ChargingStationID, MODULE_NAME, 'handleGenerateQrCodeForConnector', req.user); - // Check ConnectorID - UtilsService.assertIdIsProvided(action, filteredRequest.ConnectorID, MODULE_NAME, 'handleGenerateQrCodeForConnector', req.user); // Get the Charging Station` const chargingStation = await ChargingStationStorage.getChargingStation(req.tenant, filteredRequest.ChargingStationID); // Found ChargingStation ? @@ -672,7 +667,6 @@ export default class ChargingStationService { req.query.ChargeBoxID && (req.query.ChargingStationID = req.query.ChargeBoxID); // Filter const filteredRequest = ChargingStationValidator.getInstance().validateChargingStationOcppParametersGetReq(req.query); - UtilsService.assertIdIsProvided(action, filteredRequest.ChargingStationID, MODULE_NAME, 'handleGetChargingStationOcppParameters', req.user); // Get the Charging Station` const chargingStation = await ChargingStationStorage.getChargingStation(req.tenant, filteredRequest.ChargingStationID); // Found? @@ -699,7 +693,6 @@ export default class ChargingStationService { public static async handleRequestChargingStationOcppParameters(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise { // Filter const filteredRequest = ChargingStationValidator.getInstance().validateChargingStationOcppParametersRequestReq(req.body); - UtilsService.assertIdIsProvided(action, filteredRequest.chargingStationID, MODULE_NAME, 'handleRequestChargingStationOcppParameters', req.user); // Check auth if (!await Authorizations.canReadChargingStation(req.user)) { throw new AppAuthError({ @@ -728,9 +721,6 @@ export default class ChargingStationService { public static async handleDeleteChargingStation(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise { // Filter const chargingStationID = ChargingStationValidator.getInstance().validateChargingStationDeleteReq(req.query).ID; - // Check Mandatory fields - UtilsService.assertIdIsProvided(action, chargingStationID, MODULE_NAME, - 'handleDeleteChargingStation', req.user); // Get const chargingStation = await ChargingStationStorage.getChargingStation(req.tenant, chargingStationID); UtilsService.assertObjectExists(action, chargingStation, `Charging Station ID '${chargingStationID}' does not exist`, @@ -852,8 +842,6 @@ export default class ChargingStationService { public static async handleGetChargingStation(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise { // Filter const filteredRequest = ChargingStationValidator.getInstance().validateChargingStationGetReq({ ...req.params, ...req.query }); - // Check ID is provided - UtilsService.assertIdIsProvided(action, filteredRequest.ID, MODULE_NAME, 'handleGetChargingStation', req.user); // Check auth if (!await Authorizations.canReadChargingStation(req.user)) { throw new AppAuthError({ diff --git a/src/server/rest/v1/service/CompanyService.ts b/src/server/rest/v1/service/CompanyService.ts index 442200f152..34b02c2921 100644 --- a/src/server/rest/v1/service/CompanyService.ts +++ b/src/server/rest/v1/service/CompanyService.ts @@ -96,9 +96,9 @@ export default class CompanyService { ]; } // Check dynamic auth - const authorizationCompaniesFilter = await AuthorizationService.checkAndGetCompaniesAuthorizations( - req.tenant, req.user, filteredRequest); - if (!authorizationCompaniesFilter.authorized) { + const authorizations = await AuthorizationService.checkAndGetCompaniesAuthorizations( + req.tenant, req.user, filteredRequest, false); + if (!authorizations.authorized) { UtilsService.sendEmptyDataResult(res, next); return; } @@ -111,7 +111,7 @@ export default class CompanyService { withLogo: filteredRequest.WithLogo, locCoordinates: filteredRequest.LocCoordinates, locMaxDistanceMeters: filteredRequest.LocMaxDistanceMeters, - ...authorizationCompaniesFilter.filters + ...authorizations.filters }, { limit: filteredRequest.Limit, @@ -119,14 +119,14 @@ export default class CompanyService { sort: UtilsService.httpSortFieldsToMongoDB(filteredRequest.SortFields), onlyRecordCount: filteredRequest.OnlyRecordCount }, - authorizationCompaniesFilter.projectFields + authorizations.projectFields ); // Assign projected fields - if (authorizationCompaniesFilter.projectFields) { - companies.projectFields = authorizationCompaniesFilter.projectFields; + if (authorizations.projectFields) { + companies.projectFields = authorizations.projectFields; } // Add Auth flags - await AuthorizationService.addCompaniesAuthorizations(req.tenant, req.user, companies as CompanyDataResult, authorizationCompaniesFilter); + await AuthorizationService.addCompaniesAuthorizations(req.tenant, req.user, companies as CompanyDataResult, authorizations); res.json(companies); next(); } @@ -138,16 +138,8 @@ export default class CompanyService { // Filter const filteredRequest = CompanyValidator.getInstance().validateCompanyCreateReq(req.body); // Get dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetCompanyAuthorizations( + await AuthorizationService.checkAndGetCompanyAuthorizations( req.tenant, req.user, {}, Action.CREATE, filteredRequest); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - action: Action.CREATE, entity: Entity.COMPANY, - module: MODULE_NAME, method: 'handleCreateCompany' - }); - } // Create company const newCompany: Company = { ...filteredRequest, diff --git a/src/server/rest/v1/service/LoggingService.ts b/src/server/rest/v1/service/LogService.ts similarity index 73% rename from src/server/rest/v1/service/LoggingService.ts rename to src/server/rest/v1/service/LogService.ts index 2edb65c34b..3081486d88 100644 --- a/src/server/rest/v1/service/LoggingService.ts +++ b/src/server/rest/v1/service/LogService.ts @@ -4,23 +4,23 @@ import { NextFunction, Request, Response } from 'express'; import { Action } from '../../../../types/Authorization'; import AuthorizationService from './AuthorizationService'; import Constants from '../../../../utils/Constants'; -import { HttpLogsRequest } from '../../../../types/requests/HttpLoggingRequest'; +import { HttpLogsRequest } from '../../../../types/requests/HttpLogRequest'; import { Log } from '../../../../types/Log'; -import LoggingStorage from '../../../../storage/mongodb/LoggingStorage'; -import LoggingValidator from '../validator/LoggingValidator'; +import LogStorage from '../../../../storage/mongodb/LogStorage'; +import LogValidator from '../validator/LogValidator'; import { ServerAction } from '../../../../types/Server'; import Utils from '../../../../utils/Utils'; import UtilsService from './UtilsService'; import moment from 'moment'; -const MODULE_NAME = 'LoggingService'; +const MODULE_NAME = 'LogService'; -export default class LoggingService { +export default class LogService { public static async handleGetLogs(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise { // Filter - const filteredRequest = LoggingValidator.getInstance().validateLoggingsGetReq(req.query); + const filteredRequest = LogValidator.getInstance().validateLogsGetReq(req.query); // Get Logs - res.json(await LoggingService.getLogs(req, filteredRequest)); + res.json(await LogService.getLogs(req, filteredRequest)); next(); } @@ -28,16 +28,16 @@ export default class LoggingService { // Force params req.query.Limit = Constants.EXPORT_PAGE_SIZE.toString(); // Filter - const filteredRequest = LoggingValidator.getInstance().validateLoggingsGetReq(req.query); + const filteredRequest = LogValidator.getInstance().validateLogsGetReq(req.query); // Export await UtilsService.exportToCSV(req, res, 'exported-logs.csv', filteredRequest, - LoggingService.getLogs.bind(this), - LoggingService.convertToCSV.bind(this)); + LogService.getLogs.bind(this), + LogService.convertToCSV.bind(this)); } public static async handleGetLog(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise { // Filter - const filteredRequest = LoggingValidator.getInstance().validateLoggingGetReq(req.query); + const filteredRequest = LogValidator.getInstance().validateLogGetReq(req.query); // Check and Get Log const log = await UtilsService.checkAndGetLogAuthorization( req.tenant, req.user, filteredRequest.ID, Action.READ, action, null, null, true); @@ -45,7 +45,7 @@ export default class LoggingService { next(); } - private static convertToCSV(req: Request, loggings: Log[], writeHeader = true): string { + private static convertToCSV(req: Request, logs: Log[], writeHeader = true): string { let headers = null; // Header if (writeHeader) { @@ -64,7 +64,7 @@ export default class LoggingService { ].join(Constants.CSV_SEPARATOR); } // Content - const rows = loggings.map((log) => { + const rows = logs.map((log) => { const row = [ log.level, moment(log.timestamp).format('YYYY-MM-DD'), @@ -85,13 +85,13 @@ export default class LoggingService { private static async getLogs(req: Request, filteredRequest: HttpLogsRequest): Promise> { // Check dynamic auth - const authorizationSitesFilter = await AuthorizationService.checkAndGetLoggingsAuthorizations( - req.tenant, req.user, filteredRequest); - if (!authorizationSitesFilter.authorized) { + const authorizations = await AuthorizationService.checkAndGetLoggingsAuthorizations( + req.tenant, req.user, filteredRequest, false); + if (!authorizations.authorized) { return Constants.DB_EMPTY_DATA_RESULT; } // Get Logs - const logs = await LoggingStorage.getLogs(req.tenant, { + const logs = await LogStorage.getLogs(req.tenant, { search: filteredRequest.Search, startDateTime: filteredRequest.StartDateTime, endDateTime: filteredRequest.EndDateTime, @@ -102,20 +102,20 @@ export default class LoggingService { levels: filteredRequest.Level ? filteredRequest.Level.split('|') : null, sources: filteredRequest.Source ? filteredRequest.Source.split('|') : null, actions: filteredRequest.Action ? filteredRequest.Action.split('|') : null, - ...authorizationSitesFilter.filters + ...authorizations.filters }, { limit: filteredRequest.Limit, skip: filteredRequest.Skip, sort: UtilsService.httpSortFieldsToMongoDB(filteredRequest.SortFields), onlyRecordCount: filteredRequest.OnlyRecordCount }, - authorizationSitesFilter.projectFields); + authorizations.projectFields); // Assign projected fields - if (authorizationSitesFilter.projectFields) { - logs.projectFields = authorizationSitesFilter.projectFields; + if (authorizations.projectFields) { + logs.projectFields = authorizations.projectFields; } // Add Auth flags - await AuthorizationService.addLogsAuthorizations(req.tenant, req.user, logs as LogDataResult, authorizationSitesFilter); + await AuthorizationService.addLogsAuthorizations(req.tenant, req.user, logs as LogDataResult, authorizations); return logs; } } diff --git a/src/server/rest/v1/service/OICPEndpointService.ts b/src/server/rest/v1/service/OICPEndpointService.ts index 5abb976e5d..1b89944b4c 100644 --- a/src/server/rest/v1/service/OICPEndpointService.ts +++ b/src/server/rest/v1/service/OICPEndpointService.ts @@ -72,8 +72,6 @@ export default class OICPEndpointService { } // Filter const filteredRequest = OICPEndpointValidator.getInstance().validateOICPEndpointCreateReq(req.body); - // Check Mandatory fields - UtilsService.checkIfOICPEndpointValid(filteredRequest, req); const oicpEndpoint: OICPEndpoint = { ...filteredRequest, createdBy: { id: req.user.id }, @@ -110,8 +108,6 @@ export default class OICPEndpointService { Action.UPDATE, Entity.OICP_ENDPOINT, MODULE_NAME, 'handleUpdateOicpEndpoint'); // Filter const filteredRequest = OICPEndpointValidator.getInstance().validateOICPEndpointUpdateReq(req.body); - // Check Mandatory fields - UtilsService.checkIfOICPEndpointValid(filteredRequest, req); // Check auth if (!await Authorizations.canUpdateOicpEndpoint(req.user)) { throw new AppAuthError({ @@ -288,8 +284,6 @@ export default class OICPEndpointService { } // Filter const filteredRequest = OICPEndpointValidator.getInstance().validateOICPEndpointPingReq(req.params); - // Check Mandatory fields - UtilsService.checkIfOICPEndpointValid(filteredRequest, req); // Get oicpEndpoint const oicpEndpoint = await OICPEndpointStorage.getOicpEndpoint(req.tenant, filteredRequest.id); // Build OICP Client diff --git a/src/server/rest/v1/service/PricingService.ts b/src/server/rest/v1/service/PricingService.ts index acf3fd1437..ce22f60cef 100644 --- a/src/server/rest/v1/service/PricingService.ts +++ b/src/server/rest/v1/service/PricingService.ts @@ -54,7 +54,6 @@ export default class PricingService { Action.READ, Entity.PRICING_DEFINITION, MODULE_NAME, 'handleGetPricingDefinition'); // Filter const filteredRequest = PricingValidator.getInstance().validatePricingDefinitionGet(req.query); - UtilsService.assertIdIsProvided(action, filteredRequest.ID, MODULE_NAME, 'handleGetPricingDefinition', req.user); // Check and get pricing const pricingDefinition = await UtilsService.checkAndGetPricingDefinitionAuthorization( req.tenant, req.user, filteredRequest.ID, Action.READ, action, null, { withEntityInformation: filteredRequest.WithEntityInformation }, true); @@ -69,9 +68,9 @@ export default class PricingService { // Filter const filteredRequest = PricingValidator.getInstance().validatePricingDefinitionsGet(req.query); // Check dynamic auth - const authorizationPricingDefinitionsFilter = await AuthorizationService.checkAndGetPricingDefinitionsAuthorizations( - req.tenant, req.user, filteredRequest); - if (!authorizationPricingDefinitionsFilter.authorized) { + const authorizations = await AuthorizationService.checkAndGetPricingDefinitionsAuthorizations( + req.tenant, req.user, filteredRequest, false); + if (!authorizations.authorized) { UtilsService.sendEmptyDataResult(res, next); return; } @@ -81,21 +80,21 @@ export default class PricingService { entityID: filteredRequest.EntityID || null, entityType: filteredRequest.EntityType || null, withEntityInformation: filteredRequest?.WithEntityInformation, - ...authorizationPricingDefinitionsFilter.filters + ...authorizations.filters }, { limit: filteredRequest.Limit, skip: filteredRequest.Skip, sort: UtilsService.httpSortFieldsToMongoDB(filteredRequest.SortFields), onlyRecordCount: filteredRequest.OnlyRecordCount }, - authorizationPricingDefinitionsFilter.projectFields + authorizations.projectFields ) as PricingDefinitionDataResult; // Assign projected fields - if (authorizationPricingDefinitionsFilter.projectFields) { - pricingDefinitions.projectFields = authorizationPricingDefinitionsFilter.projectFields; + if (authorizations.projectFields) { + pricingDefinitions.projectFields = authorizations.projectFields; } // Add Auth flags - await AuthorizationService.addPricingDefinitionsAuthorizations(req.tenant, req.user, pricingDefinitions, authorizationPricingDefinitionsFilter); + await AuthorizationService.addPricingDefinitionsAuthorizations(req.tenant, req.user, pricingDefinitions, authorizations); // Alter the canCreate flag according to the pricing definition context pricingDefinitions.canCreate = await PricingService.alterCanCreate(req, action, filteredRequest.EntityType, filteredRequest.EntityID, pricingDefinitions.canCreate); res.json(pricingDefinitions); @@ -108,18 +107,9 @@ export default class PricingService { Action.CREATE, Entity.PRICING_DEFINITION, MODULE_NAME, 'handleCreatePricingDefinition'); // Filter const filteredRequest = PricingValidator.getInstance().validatePricingDefinitionCreate(req.body); - UtilsService.checkIfPricingDefinitionValid(filteredRequest, req); // Get dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetPricingDefinitionAuthorizations( + await AuthorizationService.checkAndGetPricingDefinitionAuthorizations( req.tenant, req.user, {}, Action.CREATE, filteredRequest); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - action: Action.CREATE, entity: Entity.PRICING_DEFINITION, - module: MODULE_NAME, method: 'handleCreatePricingDefinition' - }); - } // Check authorization and get the site ID depending on the entity type const siteID = await PricingService.checkAuthorizationAndGetSiteID(req, action, filteredRequest.entityType, filteredRequest.entityID); // Check that the pricing definitions can be changed for that site @@ -154,8 +144,6 @@ export default class PricingService { Action.UPDATE, Entity.PRICING_DEFINITION, MODULE_NAME, 'handleUpdatePricingDefinition'); // Filter const filteredRequest = PricingValidator.getInstance().validatePricingDefinitionUpdate(req.body); - // Check Mandatory fields - UtilsService.checkIfPricingDefinitionValid(filteredRequest, req); // Check and Get Pricing let pricingDefinition = await UtilsService.checkAndGetPricingDefinitionAuthorization( req.tenant, req.user, filteredRequest.id, Action.UPDATE, action, filteredRequest); diff --git a/src/server/rest/v1/service/RegistrationTokenService.ts b/src/server/rest/v1/service/RegistrationTokenService.ts index e3651ea2ca..d1f4b43f32 100644 --- a/src/server/rest/v1/service/RegistrationTokenService.ts +++ b/src/server/rest/v1/service/RegistrationTokenService.ts @@ -30,15 +30,8 @@ export default class RegistrationTokenService { req.tenant, req.user, filteredRequest.siteAreaID, Action.UPDATE, action, filteredRequest, null, false); } // Get dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetRegistrationTokenAuthorizations(req.tenant, req.user, {}, Action.CREATE, filteredRequest); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - action: Action.CREATE, entity: Entity.REGISTRATION_TOKEN, - module: MODULE_NAME, method: 'handleCreateRegistrationToken' - }); - } + await AuthorizationService.checkAndGetRegistrationTokenAuthorizations( + req.tenant, req.user, {}, Action.CREATE, filteredRequest); // Create const registrationToken: RegistrationToken = { siteAreaID: filteredRequest.siteAreaID, @@ -150,9 +143,9 @@ export default class RegistrationTokenService { // Filter const filteredRequest = RegistrationTokenValidator.getInstance().validateRegistrationTokensGetReq(req.query); // Check dynamic auth - const authorizationRegistrationTokenFilter = await AuthorizationService.checkAndGetRegistrationTokensAuthorizations( - req.tenant, req.user, filteredRequest); - if (!authorizationRegistrationTokenFilter.authorized) { + const authorizations = await AuthorizationService.checkAndGetRegistrationTokensAuthorizations( + req.tenant, req.user, filteredRequest, false); + if (!authorizations.authorized) { UtilsService.sendEmptyDataResult(res, next); return; } @@ -161,7 +154,7 @@ export default class RegistrationTokenService { { search: filteredRequest.Search, siteAreaIDs: filteredRequest.SiteAreaID ? filteredRequest.SiteAreaID.split('|') : null, - ...authorizationRegistrationTokenFilter.filters + ...authorizations.filters }, { limit: filteredRequest.Limit, @@ -169,14 +162,14 @@ export default class RegistrationTokenService { sort: UtilsService.httpSortFieldsToMongoDB(filteredRequest.SortFields), onlyRecordCount: filteredRequest.OnlyRecordCount }, - authorizationRegistrationTokenFilter.projectFields + authorizations.projectFields ); // Assign projected fields - if (authorizationRegistrationTokenFilter.projectFields) { - registrationTokens.projectFields = authorizationRegistrationTokenFilter.projectFields; + if (authorizations.projectFields) { + registrationTokens.projectFields = authorizations.projectFields; } // Add Auth flags - await AuthorizationService.addRegistrationTokensAuthorizations(req.tenant, req.user, registrationTokens as RegistrationTokenDataResult, authorizationRegistrationTokenFilter); + await AuthorizationService.addRegistrationTokensAuthorizations(req.tenant, req.user, registrationTokens as RegistrationTokenDataResult, authorizations); res.json(registrationTokens); next(); } diff --git a/src/server/rest/v1/service/SettingService.ts b/src/server/rest/v1/service/SettingService.ts index a3c5b44900..9b953c49c6 100644 --- a/src/server/rest/v1/service/SettingService.ts +++ b/src/server/rest/v1/service/SettingService.ts @@ -24,7 +24,6 @@ export default class SettingService { public static async handleDeleteSetting(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise { // Filter const settingID = SettingValidator.getInstance().validateSettingGetByIDReq(req.query).ID; - UtilsService.assertIdIsProvided(action, settingID, MODULE_NAME, 'handleDeleteSetting', req.user); // Check auth if (!await Authorizations.canDeleteSetting(req.user)) { throw new AppAuthError({ @@ -56,7 +55,6 @@ export default class SettingService { public static async handleGetSetting(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise { // Filter const settingID = SettingValidator.getInstance().validateSettingGetByIDReq(req.query).ID; - UtilsService.assertIdIsProvided(action, settingID, MODULE_NAME, 'handleGetSetting', req.user); // Check auth if (!await Authorizations.canReadSetting(req.user)) { throw new AppAuthError({ @@ -85,7 +83,6 @@ export default class SettingService { public static async handleGetSettingByIdentifier(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise { // Filter const settingID = SettingValidator.getInstance().validateSettingGetByIdentifierReq(req.query).Identifier; - UtilsService.assertIdIsProvided(action, settingID, MODULE_NAME, 'handleGetSettingByIdentifier', req.user); // Check auth if (!await Authorizations.canReadSetting(req.user)) { throw new AppAuthError({ @@ -172,7 +169,6 @@ export default class SettingService { } public static async handleUpdateSetting(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise { - UtilsService.assertIdIsProvided(action, req.body.id, MODULE_NAME, 'handleUpdateSetting', req.user); const filteredRequest = SettingService.filterSetting(action, req); // Check auth if (!await Authorizations.canUpdateSetting(req.user)) { diff --git a/src/server/rest/v1/service/SiteAreaService.ts b/src/server/rest/v1/service/SiteAreaService.ts index cce208e48f..3d61685896 100644 --- a/src/server/rest/v1/service/SiteAreaService.ts +++ b/src/server/rest/v1/service/SiteAreaService.ts @@ -1,14 +1,13 @@ import { Action, Entity } from '../../../../types/Authorization'; -import { HTTPAuthError, HTTPError } from '../../../../types/HTTPError'; import { NextFunction, Request, Response } from 'express'; import { ActionsResponse } from '../../../../types/GlobalType'; -import AppAuthError from '../../../../exception/AppAuthError'; import AppError from '../../../../exception/AppError'; import AuthorizationService from './AuthorizationService'; import { ChargingProfilePurposeType } from '../../../../types/ChargingProfile'; import Constants from '../../../../utils/Constants'; import ConsumptionStorage from '../../../../storage/mongodb/ConsumptionStorage'; +import { HTTPError } from '../../../../types/HTTPError'; import LockingHelper from '../../../../locking/LockingHelper'; import LockingManager from '../../../../locking/LockingManager'; import Logging from '../../../../utils/Logging'; @@ -39,15 +38,17 @@ export default class SiteAreaService { // Check and Get Site Area const authAction = action === ServerAction.ADD_ASSET_TO_SITE_AREA ? Action.ASSIGN_ASSETS_TO_SITE_AREA : Action.UNASSIGN_ASSETS_FROM_SITE_AREA; const siteArea = await UtilsService.checkAndGetSiteAreaAuthorization( - req.tenant, req.user, filteredRequest.siteAreaID, authAction, action); + req.tenant, req.user, filteredRequest.siteAreaID, authAction, action, null, { withSite: true }); // Check and Get Assets const assets = await UtilsService.checkSiteAreaAssetsAuthorization( req.tenant, req.user, siteArea, filteredRequest.assetIDs, action); // Save if (action === ServerAction.ADD_ASSET_TO_SITE_AREA) { - await SiteAreaStorage.addAssetsToSiteArea(req.tenant, siteArea, assets.map((asset) => asset.id)); + await SiteAreaStorage.addAssetsToSiteArea( + req.tenant, siteArea.id, siteArea.siteID, siteArea.site.companyID, assets.map((asset) => asset.id)); } else { - await SiteAreaStorage.removeAssetsFromSiteArea(req.tenant, filteredRequest.siteAreaID, assets.map((asset) => asset.id)); + await SiteAreaStorage.removeAssetsFromSiteArea( + req.tenant, filteredRequest.siteAreaID, assets.map((asset) => asset.id)); } await Logging.logInfo({ ...LoggingHelper.getSiteAreaProperties(siteArea), @@ -97,7 +98,7 @@ export default class SiteAreaService { // Save if (action === ServerAction.ADD_CHARGING_STATIONS_TO_SITE_AREA) { await SiteAreaStorage.addChargingStationsToSiteArea( - req.tenant, siteArea, chargingStations.map((chargingStation) => chargingStation.id)); + req.tenant, siteArea.id, siteArea.siteID, siteArea.site.companyID, chargingStations.map((chargingStation) => chargingStation.id)); } else { await SiteAreaStorage.removeChargingStationsFromSiteArea( req.tenant, filteredRequest.siteAreaID, chargingStations.map((chargingStation) => chargingStation.id)); @@ -121,7 +122,6 @@ export default class SiteAreaService { Action.DELETE, Entity.SITE_AREA, MODULE_NAME, 'handleDeleteSiteArea'); // Filter request const siteAreaID = SiteAreaValidator.getInstance().validateSiteAreaGetReq(req.query).ID; - UtilsService.assertIdIsProvided(action, siteAreaID, MODULE_NAME, 'handleDeleteSiteArea', req.user); // Check and Get Site Area const siteArea = await UtilsService.checkAndGetSiteAreaAuthorization( req.tenant, req.user, siteAreaID, Action.DELETE, action); @@ -195,9 +195,9 @@ export default class SiteAreaService { ]; } // Check dynamic auth - const authorizationSiteAreasFilter = await AuthorizationService.checkAndGetSiteAreasAuthorizations( - req.tenant, req.user, filteredRequest); - if (!authorizationSiteAreasFilter.authorized) { + const authorizations = await AuthorizationService.checkAndGetSiteAreasAuthorizations( + req.tenant, req.user, filteredRequest, false); + if (!authorizations.authorized) { UtilsService.sendEmptyDataResult(res, next); return; } @@ -213,7 +213,7 @@ export default class SiteAreaService { locMaxDistanceMeters: filteredRequest.LocMaxDistanceMeters, siteIDs: (filteredRequest.SiteID ? filteredRequest.SiteID.split('|') : null), companyIDs: (filteredRequest.CompanyID ? filteredRequest.CompanyID.split('|') : null), - ...authorizationSiteAreasFilter.filters + ...authorizations.filters }, { limit: filteredRequest.Limit, @@ -221,15 +221,15 @@ export default class SiteAreaService { sort: UtilsService.httpSortFieldsToMongoDB(filteredRequest.SortFields), onlyRecordCount: filteredRequest.OnlyRecordCount }, - authorizationSiteAreasFilter.projectFields + authorizations.projectFields ); // Assign projected fields - if (authorizationSiteAreasFilter.projectFields) { - siteAreas.projectFields = authorizationSiteAreasFilter.projectFields; + if (authorizations.projectFields) { + siteAreas.projectFields = authorizations.projectFields; } // Add Auth flags await AuthorizationService.addSiteAreasAuthorizations(req.tenant, req.user, siteAreas as SiteAreaDataResult, - authorizationSiteAreasFilter); + authorizations); res.json(siteAreas); next(); } @@ -272,21 +272,11 @@ export default class SiteAreaService { Action.CREATE, Entity.SITE_AREA, MODULE_NAME, 'handleCreateSiteArea'); // Filter request const filteredRequest = SiteAreaValidator.getInstance().validateSiteAreaCreateReq(req.body); - // Check request data is valid - UtilsService.checkIfSiteAreaValid(filteredRequest, req); - // Check auth - const authorizationFilters = await AuthorizationService.checkAndGetSiteAreaAuthorizations(req.tenant, req.user, + // Check Site Area auth + await AuthorizationService.checkAndGetSiteAreaAuthorizations(req.tenant, req.user, {}, Action.CREATE, filteredRequest); - if (!authorizationFilters.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - action: Action.CREATE, entity: Entity.SITE_AREA, - module: MODULE_NAME, method: 'handleCreateSiteArea' - }); - } // Check Site auth - const site = await UtilsService.checkAndGetSiteAuthorization( + await UtilsService.checkAndGetSiteAuthorization( req.tenant, req.user, filteredRequest.siteID, Action.UPDATE, action); // Create Site Area const siteArea: SiteArea = { @@ -315,8 +305,6 @@ export default class SiteAreaService { Action.UPDATE, Entity.SITE_AREA, MODULE_NAME, 'handleUpdateSiteArea'); // Filter request const filteredRequest = SiteAreaValidator.getInstance().validateSiteAreaUpdateReq(req.body); - // Check Mandatory fields - UtilsService.checkIfSiteAreaValid(filteredRequest, req); // Check and Get SiteArea const siteArea = await UtilsService.checkAndGetSiteAreaAuthorization( req.tenant, req.user, filteredRequest.id, Action.UPDATE, action, filteredRequest, { diff --git a/src/server/rest/v1/service/SiteService.ts b/src/server/rest/v1/service/SiteService.ts index 90ff83d6e7..e9a2808903 100644 --- a/src/server/rest/v1/service/SiteService.ts +++ b/src/server/rest/v1/service/SiteService.ts @@ -126,9 +126,9 @@ export default class SiteService { // Check Site Auth await UtilsService.checkAndGetSiteAuthorization(req.tenant, req.user, filteredRequest.SiteID, Action.READ, action); // Check dynamic auth for reading Users - const authorizationSiteUsersFilter = await AuthorizationService.checkAndGetSiteUsersAuthorizations(req.tenant, - req.user, filteredRequest); - if (!authorizationSiteUsersFilter.authorized) { + const authorizations = await AuthorizationService.checkAndGetSiteUsersAuthorizations(req.tenant, + req.user, filteredRequest, false); + if (!authorizations.authorized) { UtilsService.sendEmptyDataResult(res, next); return; } @@ -137,7 +137,7 @@ export default class SiteService { { search: filteredRequest.Search, siteIDs: [filteredRequest.SiteID], - ...authorizationSiteUsersFilter.filters + ...authorizations.filters }, { limit: filteredRequest.Limit, @@ -145,7 +145,7 @@ export default class SiteService { sort: UtilsService.httpSortFieldsToMongoDB(filteredRequest.SortFields), onlyRecordCount: filteredRequest.OnlyRecordCount }, - authorizationSiteUsersFilter.projectFields + authorizations.projectFields ); res.json(users); next(); @@ -204,9 +204,9 @@ export default class SiteService { ]; } // Check dynamic auth - const authorizationSitesFilter = await AuthorizationService.checkAndGetSitesAuthorizations( - req.tenant, req.user, filteredRequest); - if (!authorizationSitesFilter.authorized) { + const authorizations = await AuthorizationService.checkAndGetSitesAuthorizations( + req.tenant, req.user, filteredRequest, false); + if (!authorizations.authorized) { UtilsService.sendEmptyDataResult(res, next); return; } @@ -215,7 +215,7 @@ export default class SiteService { // Override Site IDs const siteAdminDataSource = await DynamicAuthorizationFactory.getDynamicDataSource( req.tenant, req.user, DynamicAuthorizationDataSourceName.SITES_ADMIN) as SitesAdminDynamicAuthorizationDataSource; - authorizationSitesFilter.filters = { ...authorizationSitesFilter.filters, ...siteAdminDataSource.getData() }; + authorizations.filters = { ...authorizations.filters, ...siteAdminDataSource.getData() }; } // Get the sites const sites = await SiteStorage.getSites(req.tenant, @@ -230,7 +230,7 @@ export default class SiteService { withAvailableChargingStations: filteredRequest.WithAvailableChargers, locCoordinates: filteredRequest.LocCoordinates, locMaxDistanceMeters: filteredRequest.LocMaxDistanceMeters, - ...authorizationSitesFilter.filters + ...authorizations.filters }, { limit: filteredRequest.Limit, @@ -238,14 +238,14 @@ export default class SiteService { sort: UtilsService.httpSortFieldsToMongoDB(filteredRequest.SortFields), onlyRecordCount: filteredRequest.OnlyRecordCount }, - authorizationSitesFilter.projectFields + authorizations.projectFields ); // Assign projected fields - if (authorizationSitesFilter.projectFields) { - sites.projectFields = authorizationSitesFilter.projectFields; + if (authorizations.projectFields) { + sites.projectFields = authorizations.projectFields; } // Add Auth flags - await AuthorizationService.addSitesAuthorizations(req.tenant, req.user, sites as SiteDataResult, authorizationSitesFilter); + await AuthorizationService.addSitesAuthorizations(req.tenant, req.user, sites as SiteDataResult, authorizations); res.json(sites); next(); } @@ -293,19 +293,9 @@ export default class SiteService { Action.CREATE, Entity.SITE, MODULE_NAME, 'handleCreateSite'); // Filter request const filteredRequest = SiteValidator.getInstance().validateSiteCreateReq(req.body); - // Check data is valid - UtilsService.checkIfSiteValid(filteredRequest, req); // Get dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetSiteAuthorizations( + await AuthorizationService.checkAndGetSiteAuthorizations( req.tenant, req.user, {}, Action.CREATE, filteredRequest); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - action: Action.CREATE, entity: Entity.SITE, - module: MODULE_NAME, method: 'handleCreateSite' - }); - } // Check Company await UtilsService.checkAndGetCompanyAuthorization( req.tenant, req.user, filteredRequest.companyID, Action.READ, action); @@ -336,8 +326,6 @@ export default class SiteService { Action.UPDATE, Entity.SITE, MODULE_NAME, 'handleUpdateSite'); // Filter request const filteredRequest = SiteValidator.getInstance().validateSiteUpdateReq(req.body); - // Check data is valid - UtilsService.checkIfSiteValid(filteredRequest, req); // Check and Get Site const site = await UtilsService.checkAndGetSiteAuthorization( req.tenant, req.user, filteredRequest.id, Action.UPDATE, action, filteredRequest); diff --git a/src/server/rest/v1/service/TagService.ts b/src/server/rest/v1/service/TagService.ts index 76fbcfa062..6a45270120 100644 --- a/src/server/rest/v1/service/TagService.ts +++ b/src/server/rest/v1/service/TagService.ts @@ -126,18 +126,9 @@ export default class TagService { public static async handleCreateTag(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise { // Filter const filteredRequest = TagValidator.getInstance().validateTagCreateReq(req.body); - UtilsService.checkIfUserTagIsValid(filteredRequest, req); // Get dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetTagAuthorizations( + await AuthorizationService.checkAndGetTagAuthorizations( req.tenant, req.user, {}, Action.CREATE, filteredRequest); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - action: Action.CREATE, entity: Entity.TAG, - module: MODULE_NAME, method: 'handleCreateTag' - }); - } // Check Tag with ID let tag = await TagStorage.getTag(req.tenant, filteredRequest.id.toUpperCase()); if (tag) { @@ -331,7 +322,6 @@ export default class TagService { public static async handleUpdateTag(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise { // Filter const filteredRequest = TagValidator.getInstance().validateTagUpdateReq({ ...req.params, ...req.body }); - UtilsService.checkIfUserTagIsValid(filteredRequest, req); // Check and Get Tag const tag = await UtilsService.checkAndGetTagAuthorization(req.tenant, req.user, filteredRequest.id, Action.UPDATE, action, filteredRequest, { withUser: true }, true); @@ -453,7 +443,7 @@ export default class TagService { await LockingManager.release(importTagsLock); } }); - await new Promise((resolve) => { + await new Promise((resolve, reject) => { // eslint-disable-next-line @typescript-eslint/no-misused-promises busboy.on('file', async (fileName: string, fileStream: Readable, fileInfo: FileInfo) => { if (fileInfo.filename.slice(-4) === '.csv') { @@ -465,7 +455,7 @@ export default class TagService { void converter.subscribe(async (tag: ImportedTag) => { // Check connection if (connectionClosed) { - throw new Error('HTTP connection has been closed'); + reject(new Error('HTTP connection has been closed')); } // Check the format of the first entry if (!result.inSuccess && !result.inError) { @@ -477,7 +467,7 @@ export default class TagService { res.end(); resolve(); } - throw new Error(`Missing one of required properties: '${TagRequiredImportProperties.join(', ')}'`); + reject(new Error(`Missing one of required properties: '${TagRequiredImportProperties.join(', ')}'`)); } } // Set default value @@ -782,9 +772,9 @@ export default class TagService { private static async getTags(req: Request, filteredRequest: HttpTagsRequest): Promise> { // Get authorization filters - const authorizationTagsFilters = await AuthorizationService.checkAndGetTagsAuthorizations( - req.tenant, req.user, filteredRequest); - if (!authorizationTagsFilters.authorized) { + const authorizations = await AuthorizationService.checkAndGetTagsAuthorizations( + req.tenant, req.user, filteredRequest, false); + if (!authorizations.authorized) { return Constants.DB_EMPTY_DATA_RESULT; } // Get the tags @@ -795,7 +785,7 @@ export default class TagService { active: filteredRequest.Active, withUser: filteredRequest.WithUser, userIDs: (filteredRequest.UserID ? filteredRequest.UserID.split('|') : null), - ...authorizationTagsFilters.filters + ...authorizations.filters }, { limit: filteredRequest.Limit, @@ -803,14 +793,14 @@ export default class TagService { sort: UtilsService.httpSortFieldsToMongoDB(filteredRequest.SortFields), onlyRecordCount: filteredRequest.OnlyRecordCount }, - authorizationTagsFilters.projectFields, + authorizations.projectFields, ); // Assign projected fields - if (authorizationTagsFilters.projectFields) { - tags.projectFields = authorizationTagsFilters.projectFields; + if (authorizations.projectFields) { + tags.projectFields = authorizations.projectFields; } // Add Auth flags - await AuthorizationService.addTagsAuthorizations(req.tenant, req.user, tags as TagDataResult, authorizationTagsFilters); + await AuthorizationService.addTagsAuthorizations(req.tenant, req.user, tags as TagDataResult, authorizations); return tags; } diff --git a/src/server/rest/v1/service/TransactionService.ts b/src/server/rest/v1/service/TransactionService.ts index 188020339a..a2a5cc8b47 100644 --- a/src/server/rest/v1/service/TransactionService.ts +++ b/src/server/rest/v1/service/TransactionService.ts @@ -339,12 +339,12 @@ export default class TransactionService { // Get data const { transaction, chargingStation, connector } = await TransactionService.checkAndGetTransactionChargingStationConnector(action, req.tenant, req.user, transactionID); + req.body.chargingStationID = transaction.chargeBoxID; + req.body.args = { transactionId: transaction.id }; // Handle the routing if (chargingStation.issuer) { // OCPP Remote Stop if (!chargingStation.inactive && connector.currentTransactionID === transaction.id) { - req.body.chargingStationID = transaction.chargeBoxID; - req.body.args = { transactionId: transaction.id }; await ChargingStationService.handleOcppAction(ServerAction.CHARGING_STATION_REMOTE_STOP_TRANSACTION, req, res, next); // Transaction Soft Stop } else { @@ -352,8 +352,14 @@ export default class TransactionService { transaction, chargingStation, connector, req, res, next); } } else { - // OCPI Remote Stop - await ChargingStationService.handleOcpiAction(ServerAction.OCPI_EMSP_STOP_SESSION, req, res, next); + // eslint-disable-next-line no-lonely-if + if (connector.currentTransactionID === transaction.id) { + // OCPI Remote Stop + await ChargingStationService.handleOcpiAction(ServerAction.OCPI_EMSP_STOP_SESSION, req, res, next); + } else { + await TransactionService.transactionSoftStop(ServerAction.TRANSACTION_SOFT_STOP, + transaction, chargingStation, connector, req, res, next); + } } } @@ -457,11 +463,11 @@ export default class TransactionService { } else { consumptions = await ConsumptionStorage.getOptimizedTransactionConsumptions( req.tenant, { transactionId: transaction.id }, [ - 'consumptions.startedAt', 'consumptions.cumulatedConsumptionWh', 'consumptions.cumulatedConsumptionAmps', 'consumptions.cumulatedAmount', - 'consumptions.stateOfCharge', 'consumptions.limitWatts', 'consumptions.limitAmps', 'consumptions.startedAt', 'consumptions.endedAt', - 'consumptions.instantVoltsDC', 'consumptions.instantVolts', 'consumptions.instantVoltsL1', 'consumptions.instantVoltsL2', 'consumptions.instantVoltsL3', - 'consumptions.instantWattsDC', 'consumptions.instantWatts', 'consumptions.instantWattsL1', 'consumptions.instantWattsL2', 'consumptions.instantWattsL3', - 'consumptions.instantAmpsDC', 'consumptions.instantAmps', 'consumptions.instantAmpsL1', 'consumptions.instantAmpsL2', 'consumptions.instantAmpsL3' + 'startedAt', 'endedAt', 'cumulatedConsumptionWh', 'cumulatedConsumptionAmps', 'cumulatedAmount', + 'stateOfCharge', 'limitWatts', 'limitAmps', + 'instantVoltsDC', 'instantVolts', 'instantVoltsL1', 'instantVoltsL2', 'instantVoltsL3', + 'instantWattsDC', 'instantWatts', 'instantWattsL1', 'instantWattsL2', 'instantWattsL3', + 'instantAmpsDC', 'instantAmps', 'instantAmpsL1', 'instantAmpsL2', 'instantAmpsL3' ]); } // Assign diff --git a/src/server/rest/v1/service/UserService.ts b/src/server/rest/v1/service/UserService.ts index 5649042ae9..465284917c 100644 --- a/src/server/rest/v1/service/UserService.ts +++ b/src/server/rest/v1/service/UserService.ts @@ -339,9 +339,9 @@ export default class UserService { return; } // Check dynamic auth for reading Sites - const authorizationUserSitesFilters = await AuthorizationService.checkAndGetUserSitesAuthorizations(req.tenant, + const authorizations = await AuthorizationService.checkAndGetUserSitesAuthorizations(req.tenant, req.user, filteredRequest); - if (!authorizationUserSitesFilters.authorized) { + if (!authorizations.authorized) { UtilsService.sendEmptyDataResult(res, next); return; } @@ -350,7 +350,7 @@ export default class UserService { { search: filteredRequest.Search, userIDs: [filteredRequest.UserID], - ...authorizationUserSitesFilters.filters + ...authorizations.filters }, { limit: filteredRequest.Limit, @@ -358,7 +358,7 @@ export default class UserService { sort: UtilsService.httpSortFieldsToMongoDB(filteredRequest.SortFields), onlyRecordCount: filteredRequest.OnlyRecordCount }, - authorizationUserSitesFilters.projectFields + authorizations.projectFields ); // Filter sites.result = sites.result.map((userSite) => ({ @@ -383,7 +383,7 @@ export default class UserService { // Filter const filteredRequest = UserValidator.getInstance().validateUsersInErrorGetReq(req.query); // Get authorization filters - const authorizationUserInErrorFilters = await AuthorizationService.checkAndGetUsersInErrorAuthorizations( + const authorizations = await AuthorizationService.checkAndGetUsersInErrorAuthorizations( req.tenant, req.user, filteredRequest); // Get users const users = await UserStorage.getUsersInError(req.tenant, @@ -391,7 +391,7 @@ export default class UserService { search: filteredRequest.Search, roles: (filteredRequest.Role ? filteredRequest.Role.split('|') : null), errorTypes: (filteredRequest.ErrorType ? filteredRequest.ErrorType.split('|') : Object.values(UserInErrorType)), - ...authorizationUserInErrorFilters.filters + ...authorizations.filters }, { limit: filteredRequest.Limit, @@ -399,10 +399,10 @@ export default class UserService { skip: filteredRequest.Skip, sort: UtilsService.httpSortFieldsToMongoDB(filteredRequest.SortFields) }, - authorizationUserInErrorFilters.projectFields + authorizations.projectFields ); // Add Auth flags - await AuthorizationService.addUsersAuthorizations(req.tenant, req.user, users as UserDataResult, authorizationUserInErrorFilters); + await AuthorizationService.addUsersAuthorizations(req.tenant, req.user, users as UserDataResult, authorizations); res.json(users); next(); } @@ -454,7 +454,7 @@ export default class UserService { await LockingManager.release(importUsersLock); } }); - await new Promise((resolve) => { + await new Promise((resolve, reject) => { // eslint-disable-next-line @typescript-eslint/no-misused-promises busboy.on('file', async (fileName: string, fileStream: Readable, fileInfo: FileInfo) => { if (fileInfo.filename.slice(-4) === '.csv') { @@ -466,7 +466,7 @@ export default class UserService { void converter.subscribe(async (user: ImportedUser) => { // Check connection if (connectionClosed) { - throw new Error('HTTP connection has been closed'); + reject(new Error('HTTP connection has been closed')); } // Check the format of the first entry if (!result.inSuccess && !result.inError) { @@ -478,7 +478,7 @@ export default class UserService { res.end(); resolve(); } - throw new Error(`Missing one of required properties: '${UserRequiredImportProperties.join(', ')}'`); + reject(new Error(`Missing one of required properties: '${UserRequiredImportProperties.join(', ')}'`)); } } // Set default value @@ -621,16 +621,8 @@ export default class UserService { // Check Mandatory fields UtilsService.checkIfUserValid(filteredRequest, null, req); // Get dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetUserAuthorizations( + const authorizations = await AuthorizationService.checkAndGetUserAuthorizations( req.tenant, req.user, {}, Action.CREATE, filteredRequest); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: req.user, - action: Action.READ, entity: Entity.SITE, - module: MODULE_NAME, method: 'handleCreateSite' - }); - } // Get the email const foundUser = await UserStorage.getUserByEmail(req.tenant, filteredRequest.email); if (foundUser) { @@ -665,9 +657,9 @@ export default class UserService { }); } // Update User Admin Data - await UserService.updateUserAdminData(req.tenant, newUser, authorizationFilter.projectFields); + await UserService.updateUserAdminData(req.tenant, newUser, authorizations.projectFields); // Assign Site to new User - await UtilsService.assignCreatedUserToSites(req.tenant, newUser, authorizationFilter); + await UtilsService.assignCreatedUserToSites(req.tenant, newUser, authorizations); // Update Billing await UserService.updateUserBilling(ServerAction.USER_CREATE, req.tenant, req.user, newUser); // Log @@ -742,9 +734,9 @@ export default class UserService { private static async getUsers(req: Request, filteredRequest: HttpUsersRequest): Promise> { // Get authorization filters - const authorizationUsersFilters = await AuthorizationService.checkAndGetUsersAuthorizations( - req.tenant, req.user, filteredRequest); - if (!authorizationUsersFilters.authorized) { + const authorizations = await AuthorizationService.checkAndGetUsersAuthorizations( + req.tenant, req.user, filteredRequest, false); + if (!authorizations.authorized) { return Constants.DB_EMPTY_DATA_RESULT; } // Optimization: Get Tag IDs from Visual IDs @@ -770,7 +762,7 @@ export default class UserService { technical: Utils.isBoolean(filteredRequest.Technical) ? filteredRequest.Technical : null, freeAccess: Utils.isBoolean(filteredRequest.FreeAccess) ? filteredRequest.FreeAccess : null, excludeSiteID: filteredRequest.ExcludeSiteID, - ...authorizationUsersFilters.filters + ...authorizations.filters }, { limit: filteredRequest.Limit, @@ -778,14 +770,14 @@ export default class UserService { sort: UtilsService.httpSortFieldsToMongoDB(filteredRequest.SortFields), onlyRecordCount: filteredRequest.OnlyRecordCount }, - authorizationUsersFilters.projectFields + authorizations.projectFields ); // Assign projected fields - if (authorizationUsersFilters.projectFields) { - users.projectFields = authorizationUsersFilters.projectFields; + if (authorizations.projectFields) { + users.projectFields = authorizations.projectFields; } // Add Auth flags - await AuthorizationService.addUsersAuthorizations(req.tenant, req.user, users as UserDataResult, authorizationUsersFilters); + await AuthorizationService.addUsersAuthorizations(req.tenant, req.user, users as UserDataResult, authorizations); return users; } diff --git a/src/server/rest/v1/service/UtilsService.ts b/src/server/rest/v1/service/UtilsService.ts index 5beb945b5a..fad73a95fd 100644 --- a/src/server/rest/v1/service/UtilsService.ts +++ b/src/server/rest/v1/service/UtilsService.ts @@ -1,6 +1,6 @@ import { Action, AuthorizationFilter, Entity } from '../../../../types/Authorization'; import { Car, CarCatalog } from '../../../../types/Car'; -import ChargingStation, { ChargePoint, Voltage } from '../../../../types/ChargingStation'; +import ChargingStation, { ChargePoint } from '../../../../types/ChargingStation'; import { HTTPAuthError, HTTPError } from '../../../../types/HTTPError'; import { NextFunction, Request, Response } from 'express'; import Tenant, { TenantComponents } from '../../../../types/Tenant'; @@ -13,6 +13,9 @@ import AssetStorage from '../../../../storage/mongodb/AssetStorage'; import AuthorizationService from './AuthorizationService'; import Authorizations from '../../../../authorization/Authorizations'; import AxiosFactory from '../../../../utils/AxiosFactory'; +import { BillingInvoice } from '../../../../types/Billing'; +import { BillingSettings } from '../../../../types/Setting'; +import BillingStorage from '../../../../storage/mongodb/BillingStorage'; import CarStorage from '../../../../storage/mongodb/CarStorage'; import CentralSystemRestServiceConfiguration from '../../../../types/configuration/CentralSystemRestServiceConfiguration'; import { ChargingProfile } from '../../../../types/ChargingProfile'; @@ -24,17 +27,16 @@ import Cypher from '../../../../utils/Cypher'; import { DataResult } from '../../../../types/DataResult'; import { EntityData } from '../../../../types/GlobalType'; import { Log } from '../../../../types/Log'; +import LogStorage from '../../../../storage/mongodb/LogStorage'; import Logging from '../../../../utils/Logging'; import LoggingHelper from '../../../../utils/LoggingHelper'; -import LoggingStorage from '../../../../storage/mongodb/LoggingStorage'; -import OCPIEndpoint from '../../../../types/ocpi/OCPIEndpoint'; -import OICPEndpoint from '../../../../types/oicp/OICPEndpoint'; import PDFDocument from 'pdfkit'; import PricingDefinition from '../../../../types/Pricing'; import PricingStorage from '../../../../storage/mongodb/PricingStorage'; import RegistrationToken from '../../../../types/RegistrationToken'; import RegistrationTokenStorage from '../../../../storage/mongodb/RegistrationTokenStorage'; import { ServerAction } from '../../../../types/Server'; +import SettingStorage from '../../../../storage/mongodb/SettingStorage'; import Site from '../../../../types/Site'; import SiteArea from '../../../../types/SiteArea'; import SiteAreaStorage from '../../../../storage/mongodb/SiteAreaStorage'; @@ -46,7 +48,6 @@ import UserStorage from '../../../../storage/mongodb/UserStorage'; import UserToken from '../../../../types/UserToken'; import Utils from '../../../../utils/Utils'; import _ from 'lodash'; -import countries from 'i18n-iso-countries'; import moment from 'moment'; const MODULE_NAME = 'UtilsService'; @@ -95,6 +96,7 @@ export default class UtilsService { }); } + // TODO: Not yet migrated to the new authorization framework public static async checkAndGetChargingStationAuthorization(tenant: Tenant, userToken: UserToken, chargingStationID: string, authAction: Action, action: ServerAction, entityData?: EntityData, additionalFilters: Record = {}, applyProjectFields = false): Promise { // Check static auth for reading Charging Station @@ -111,9 +113,9 @@ export default class UtilsService { // Check mandatory fields UtilsService.assertIdIsProvided(action, chargingStationID, MODULE_NAME, 'checkAndGetChargingStationAuthorization', userToken); // Get dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetChargingStationAuthorizations( + const authorizations = await AuthorizationService.checkAndGetChargingStationAuthorizations( tenant, userToken, { ID: chargingStationID }, authAction, entityData); - if (!authorizationFilter.authorized) { + if (!authorizations.authorized) { throw new AppAuthError({ errorCode: HTTPAuthError.FORBIDDEN, user: userToken, @@ -125,9 +127,9 @@ export default class UtilsService { const chargingStation = await ChargingStationStorage.getChargingStation(tenant, chargingStationID, { ...additionalFilters, - ...authorizationFilter.filters + ...authorizations.filters }, - applyProjectFields ? authorizationFilter.projectFields : null + applyProjectFields ? authorizations.projectFields : null ); UtilsService.assertObjectExists(action, chargingStation, `ChargingStation ID '${chargingStationID}' does not exist`, MODULE_NAME, 'checkAndGetChargingStationAuthorization', userToken); @@ -150,36 +152,27 @@ export default class UtilsService { // Check mandatory fields UtilsService.assertIdIsProvided(action, pricingDefinitionID, MODULE_NAME, 'checkAndGetPricingDefinitionAuthorization', userToken); // Get dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetPricingDefinitionAuthorizations( + const authorizations = await AuthorizationService.checkAndGetPricingDefinitionAuthorizations( tenant, userToken, { ID: pricingDefinitionID }, authAction, entityData); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: userToken, - action: authAction, entity: Entity.PRICING_DEFINITION, - module: MODULE_NAME, method: 'checkAndGetPricingDefinitionAuthorization', - value: pricingDefinitionID - }); - } // Get Pricing const pricingDefinition = await PricingStorage.getPricingDefinition(tenant, pricingDefinitionID, { ...additionalFilters, - ...authorizationFilter.filters + ...authorizations.filters }, - applyProjectFields ? authorizationFilter.projectFields : null + applyProjectFields ? authorizations.projectFields : null ); UtilsService.assertObjectExists(action, pricingDefinition, `Pricing Model ID '${pricingDefinitionID}' does not exist`, MODULE_NAME, 'checkAndGetPricingDefinitionAuthorization', userToken); // Add actions - await AuthorizationService.addPricingDefinitionAuthorizations(tenant, userToken, pricingDefinition, authorizationFilter); + await AuthorizationService.addPricingDefinitionAuthorizations(tenant, userToken, pricingDefinition, authorizations); // Assign projected fields - if (authorizationFilter.projectFields) { - pricingDefinition.projectFields = authorizationFilter.projectFields; + if (authorizations.projectFields) { + pricingDefinition.projectFields = authorizations.projectFields; } // Assign Metadata - if (authorizationFilter.metadata) { - pricingDefinition.metadata = authorizationFilter.metadata; + if (authorizations.metadata) { + pricingDefinition.metadata = authorizations.metadata; } const authorized = AuthorizationService.canPerformAction(pricingDefinition, authAction); if (!authorized) { @@ -199,37 +192,28 @@ export default class UtilsService { // Check mandatory fields UtilsService.assertIdIsProvided(action, registrationTokenID, MODULE_NAME, 'checkAndGetRegistrationTokenAuthorization', userToken); // Get dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetRegistrationTokenAuthorizations( + const authorizations = await AuthorizationService.checkAndGetRegistrationTokenAuthorizations( tenant, userToken, { ID: registrationTokenID }, authAction, entityData); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: userToken, - action: authAction, entity: Entity.REGISTRATION_TOKEN, - module: MODULE_NAME, method: 'checkAndGetRegistrationTokenAuthorization', - value: registrationTokenID, - }); - } // Get Registration Token const registrationToken = await RegistrationTokenStorage.getRegistrationToken(tenant, registrationTokenID, { ...additionalFilters, - ...authorizationFilter.filters + ...authorizations.filters }, - applyProjectFields ? authorizationFilter.projectFields : null + applyProjectFields ? authorizations.projectFields : null ); UtilsService.assertObjectExists(action, registrationToken, `Registration Token ID '${registrationTokenID}' does not exist`, MODULE_NAME, 'checkAndGetRegistrationTokenAuthorization', userToken); // Assign projected fields - if (authorizationFilter.projectFields) { - registrationToken.projectFields = authorizationFilter.projectFields; + if (authorizations.projectFields) { + registrationToken.projectFields = authorizations.projectFields; } // Assign Metadata - if (authorizationFilter.metadata) { - registrationToken.metadata = authorizationFilter.metadata; + if (authorizations.metadata) { + registrationToken.metadata = authorizations.metadata; } // Add actions - await AuthorizationService.addRegistrationTokenAuthorizations(tenant, userToken, registrationToken, authorizationFilter); + await AuthorizationService.addRegistrationTokenAuthorizations(tenant, userToken, registrationToken, authorizations); const authorized = AuthorizationService.canPerformAction(registrationToken, authAction); if (!authorized) { throw new AppAuthError({ @@ -248,38 +232,28 @@ export default class UtilsService { // Check mandatory fields UtilsService.assertIdIsProvided(action, companyID, MODULE_NAME, 'checkAndGetCompanyAuthorization', userToken); // Get dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetCompanyAuthorizations( + const authorizations = await AuthorizationService.checkAndGetCompanyAuthorizations( tenant, userToken, { ID: companyID }, authAction, entityData); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: userToken, - action: authAction, entity: Entity.COMPANY, - module: MODULE_NAME, method: 'checkAndGetCompanyAuthorization', - value: companyID, - companyID: companyID, - }); - } // Get Company const company = await CompanyStorage.getCompany(tenant, companyID, { ...additionalFilters, - ...authorizationFilter.filters + ...authorizations.filters }, - applyProjectFields ? authorizationFilter.projectFields : null + applyProjectFields ? authorizations.projectFields : null ); UtilsService.assertObjectExists(action, company, `Company ID '${companyID}' does not exist`, MODULE_NAME, 'checkAndGetCompanyAuthorization', userToken); // Assign projected fields - if (authorizationFilter.projectFields) { - company.projectFields = authorizationFilter.projectFields; + if (authorizations.projectFields) { + company.projectFields = authorizations.projectFields; } // Assign Metadata - if (authorizationFilter.metadata) { - company.metadata = authorizationFilter.metadata; + if (authorizations.metadata) { + company.metadata = authorizations.metadata; } // Add actions - await AuthorizationService.addCompanyAuthorizations(tenant, userToken, company, authorizationFilter); + await AuthorizationService.addCompanyAuthorizations(tenant, userToken, company, authorizations); const authorized = AuthorizationService.canPerformAction(company, authAction); if (!authorized) { throw new AppAuthError({ @@ -299,24 +273,15 @@ export default class UtilsService { // Check mandatory fields UtilsService.assertIdIsProvided(action, userID, MODULE_NAME, 'checkAndGetUserAuthorization', userToken); // Get dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetUserAuthorizations( + const authorizations = await AuthorizationService.checkAndGetUserAuthorizations( tenant, userToken, { ID: userID }, authAction, entityData); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: userToken, - action: authAction, entity: Entity.USER, - module: MODULE_NAME, method: 'checkAndGetUserAuthorization', - value: userID - }); - } // Get User const user = await UserStorage.getUser(tenant, userID, { ...additionalFilters, - ...authorizationFilter.filters + ...authorizations.filters }, - applyProjectFields ? authorizationFilter.projectFields : null + applyProjectFields ? authorizations.projectFields : null ); UtilsService.assertObjectExists(action, user, `User ID '${userID}' does not exist`, MODULE_NAME, 'checkAndGetUserAuthorization', userToken); @@ -332,15 +297,15 @@ export default class UtilsService { }); } // Assign projected fields - if (authorizationFilter.projectFields) { - user.projectFields = authorizationFilter.projectFields; + if (authorizations.projectFields) { + user.projectFields = authorizations.projectFields; } // Assign Metadata - if (authorizationFilter.metadata) { - user.metadata = authorizationFilter.metadata; + if (authorizations.metadata) { + user.metadata = authorizations.metadata; } // Add actions - await AuthorizationService.addUserAuthorizations(tenant, userToken, user, authorizationFilter); + await AuthorizationService.addUserAuthorizations(tenant, userToken, user, authorizations); const authorized = AuthorizationService.canPerformAction(user, authAction); if (!authorized) { throw new AppAuthError({ @@ -359,38 +324,28 @@ export default class UtilsService { // Check mandatory fields UtilsService.assertIdIsProvided(action, siteID, MODULE_NAME, 'checkAndGetSiteAuthorization', userToken); // Get dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetSiteAuthorizations( + const authorizations = await AuthorizationService.checkAndGetSiteAuthorizations( tenant, userToken, { ID: siteID }, authAction, entityData); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: userToken, - action: authAction, entity: Entity.SITE, - module: MODULE_NAME, method: 'checkAndGetSiteAuthorization', - value: siteID, - siteID: siteID, - }); - } // Get Site const site = await SiteStorage.getSite(tenant, siteID, { ...additionalFilters, - ...authorizationFilter.filters, + ...authorizations.filters, }, - applyProjectFields ? authorizationFilter.projectFields : null + applyProjectFields ? authorizations.projectFields : null ); UtilsService.assertObjectExists(action, site, `Site ID '${siteID}' does not exist`, MODULE_NAME, 'checkAndGetSiteAuthorization', userToken); // Assign projected fields - if (authorizationFilter.projectFields) { - site.projectFields = authorizationFilter.projectFields; + if (authorizations.projectFields) { + site.projectFields = authorizations.projectFields; } // Assign Metadata - if (authorizationFilter.metadata) { - site.metadata = authorizationFilter.metadata; + if (authorizations.metadata) { + site.metadata = authorizations.metadata; } // Add actions - await AuthorizationService.addSiteAuthorizations(tenant, userToken, site, authorizationFilter); + await AuthorizationService.addSiteAuthorizations(tenant, userToken, site, authorizations); const authorized = AuthorizationService.canPerformAction(site, authAction); if (!authorized) { throw new AppAuthError({ @@ -410,40 +365,30 @@ export default class UtilsService { // Check mandatory fields failsafe, should already be done in the json schema validation for each request UtilsService.assertIdIsProvided(action, assetID, MODULE_NAME, 'checkAndGetAssetAuthorization', userToken); // Retrieve authorization for action - const authorizationFilter = await AuthorizationService.checkAndGetAssetAuthorizations( + const authorizations = await AuthorizationService.checkAndGetAssetAuthorizations( tenant, userToken, authAction, { ID: assetID }, entityData); - // In certain cases the authorization filter will pass - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: userToken, - action: authAction, entity: Entity.ASSET, - module: MODULE_NAME, method: 'checkAndGetAssetAuthorization', - value: assetID, - }); - } // Retrieve Asset from storage const asset = await AssetStorage.getAsset(tenant, assetID, { ...additionalFilters, - ...authorizationFilter.filters + ...authorizations.filters }, - applyProjectFields ? authorizationFilter.projectFields : null + applyProjectFields ? authorizations.projectFields : null ); // Check object not empty UtilsService.assertObjectExists(action, asset, `Asset ID '${assetID}' cannot be retrieved`, MODULE_NAME, 'checkAndGetAssetAuthorization', userToken); // Assign projected fields - if (authorizationFilter.projectFields) { - asset.projectFields = authorizationFilter.projectFields; + if (authorizations.projectFields) { + asset.projectFields = authorizations.projectFields; } // Assign Metadata - if (authorizationFilter.metadata) { - asset.metadata = authorizationFilter.metadata; + if (authorizations.metadata) { + asset.metadata = authorizations.metadata; } // Add entity authorization - await AuthorizationService.addAssetAuthorizations(tenant, userToken, asset, authorizationFilter); + await AuthorizationService.addAssetAuthorizations(tenant, userToken, asset, authorizations); // Check authorization on retrieved entity const authorized = AuthorizationService.canPerformAction(asset, authAction); if (!authorized) { @@ -464,37 +409,28 @@ export default class UtilsService { // Check mandatory fields UtilsService.assertIdIsProvided(action, logID, MODULE_NAME, 'checkAndGetLogAuthorization', userToken); // Get dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetLoggingAuthorizations( + const authorizations = await AuthorizationService.checkAndGetLoggingAuthorizations( tenant, userToken, { ID: logID }, authAction, entityData); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: userToken, - action: authAction, entity: Entity.LOGGING, - module: MODULE_NAME, method: 'checkAndGetLogAuthorization', - value: logID - }); - } // Get Log - const log = await LoggingStorage.getLog(tenant, logID, + const log = await LogStorage.getLog(tenant, logID, { ...additionalFilters, - ...authorizationFilter.filters, + ...authorizations.filters, }, - applyProjectFields ? authorizationFilter.projectFields : null + applyProjectFields ? authorizations.projectFields : null ); UtilsService.assertObjectExists(action, log, `Log ID '${logID}' does not exist`, MODULE_NAME, 'checkAndGetLogAuthorization', userToken); // Assign projected fields - if (authorizationFilter.projectFields) { - log.projectFields = authorizationFilter.projectFields; + if (authorizations.projectFields) { + log.projectFields = authorizations.projectFields; } // Assign Metadata - if (authorizationFilter.metadata) { - log.metadata = authorizationFilter.metadata; + if (authorizations.metadata) { + log.metadata = authorizations.metadata; } // Add actions - AuthorizationService.addLogAuthorizations(tenant, userToken, log, authorizationFilter); + AuthorizationService.addLogAuthorizations(tenant, userToken, log, authorizations); const authorized = AuthorizationService.canPerformAction(log, authAction); if (!authorized) { throw new AppAuthError({ @@ -521,25 +457,16 @@ export default class UtilsService { }); } // Check dynamic auth for assignment - const authorizationFilter = await AuthorizationService.checkAndAssignUserSitesAuthorizations( + const authorizations = await AuthorizationService.checkAndAssignUserSitesAuthorizations( tenant, action, userToken, { userID: user.id, siteIDs }); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: userToken, - action: action === ServerAction.ADD_SITES_TO_USER ? Action.ASSIGN : Action.UNASSIGN, - entity: Entity.USERS_SITES, - module: MODULE_NAME, method: 'checkUserSitesAuthorization', - }); - } // Get Sites let sites = (await SiteStorage.getSites(tenant, { siteIDs, ...additionalFilters, - ...authorizationFilter.filters, + ...authorizations.filters, }, Constants.DB_PARAMS_MAX_LIMIT, - applyProjectFields ? authorizationFilter.projectFields : null + applyProjectFields ? authorizations.projectFields : null )).result; // Keep the relevant result sites = sites.filter((site) => siteIDs.includes(site.id)); @@ -569,25 +496,16 @@ export default class UtilsService { }); } // Check dynamic auth for assignment - const authorizationFilter = await AuthorizationService.checkAssignSiteUsersAuthorizations( + const authorizations = await AuthorizationService.checkAssignSiteUsersAuthorizations( tenant, action, userToken, { siteID: site.id, userIDs }); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: userToken, - action: action === ServerAction.ADD_USERS_TO_SITE ? Action.ASSIGN : Action.UNASSIGN, - entity: Entity.USERS_SITES, - module: MODULE_NAME, method: 'checkSiteUsersAuthorization', - }); - } // Get Users let users = (await UserStorage.getUsers(tenant, { userIDs, ...additionalFilters, - ...authorizationFilter.filters, + ...authorizations.filters, }, Constants.DB_PARAMS_MAX_LIMIT, - applyProjectFields ? authorizationFilter.projectFields : null + applyProjectFields ? authorizations.projectFields : null )).result; // Keep the relevant result users = users.filter((user) => userIDs.includes(user.id)); @@ -617,24 +535,16 @@ export default class UtilsService { }); } // Check dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetAssetsAuthorizations(tenant, userToken, Action.LIST); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: userToken, - action: Action.LIST, - entity: Entity.ASSET, - module: MODULE_NAME, method: 'checkAndGetAssetsAuthorization', - }); - } + const authorizations = await AuthorizationService.checkAndGetAssetsAuthorizations( + tenant, userToken, Action.LIST); // Get Assets const assets = (await AssetStorage.getAssets(tenant, { assetIDs, ...additionalFilters, - ...authorizationFilter.filters, + ...authorizations.filters, }, Constants.DB_PARAMS_MAX_LIMIT, - applyProjectFields ? authorizationFilter.projectFields : null + applyProjectFields ? authorizations.projectFields : null )).result; // Must have the same result if (assetIDs.length !== assets.length) { @@ -663,24 +573,15 @@ export default class UtilsService { }); } // Check dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetChargingStationsAuthorizations(tenant, userToken); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: userToken, - action: Action.LIST, - entity: Entity.CHARGING_STATION, - module: MODULE_NAME, method: 'checkAndGetChargingStationsAuthorization', - }); - } + const authorizations = await AuthorizationService.checkAndGetChargingStationsAuthorizations(tenant, userToken); // Get Charging Stations const chargingStations = (await ChargingStationStorage.getChargingStations(tenant, { chargingStationIDs, ...additionalFilters, - ...authorizationFilter.filters, + ...authorizations.filters, }, Constants.DB_PARAMS_MAX_LIMIT, - applyProjectFields ? authorizationFilter.projectFields : null + applyProjectFields ? authorizations.projectFields : null )).result; // Must have the same result if (chargingStationIDs.length !== chargingStations.length) { @@ -700,38 +601,28 @@ export default class UtilsService { // Check mandatory fields UtilsService.assertIdIsProvided(action, siteAreaID, MODULE_NAME, 'checkAndGetSiteAreaAuthorization', userToken); // Get dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetSiteAreaAuthorizations( + const authorizations = await AuthorizationService.checkAndGetSiteAreaAuthorizations( tenant, userToken, { ID: siteAreaID }, authAction, entityData); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: userToken, - action: authAction, entity: Entity.SITE_AREA, - module: MODULE_NAME, method: 'checkAndGetSiteAreaAuthorization', - value: siteAreaID, - siteAreaID: siteAreaID, - }); - } // Get SiteArea & check it exists const siteArea = await SiteAreaStorage.getSiteArea(tenant, siteAreaID, { ...additionalFilters, - ...authorizationFilter.filters, + ...authorizations.filters, }, - applyProjectFields ? authorizationFilter.projectFields : null + applyProjectFields ? authorizations.projectFields : null ); UtilsService.assertObjectExists(action, siteArea, `Site Area ID '${siteAreaID}' does not exist`, MODULE_NAME, 'checkAndGetSiteAreaAuthorization', userToken); // Assign projected fields - if (authorizationFilter.projectFields) { - siteArea.projectFields = authorizationFilter.projectFields; + if (authorizations.projectFields) { + siteArea.projectFields = authorizations.projectFields; } // Assign Metadata - if (authorizationFilter.metadata) { - siteArea.metadata = authorizationFilter.metadata; + if (authorizations.metadata) { + siteArea.metadata = authorizations.metadata; } // Add actions - await AuthorizationService.addSiteAreaAuthorizations(tenant, userToken, siteArea, authorizationFilter); + await AuthorizationService.addSiteAreaAuthorizations(tenant, userToken, siteArea, authorizations); const authorized = AuthorizationService.canPerformAction(siteArea, authAction); if (!authorized) { throw new AppAuthError({ @@ -751,37 +642,28 @@ export default class UtilsService { // Check mandatory fields UtilsService.assertIdIsProvided(action, carID, MODULE_NAME, 'checkAndGetCarAuthorization', userToken); // Get dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetCarAuthorizations( + const authorizations = await AuthorizationService.checkAndGetCarAuthorizations( tenant, userToken, { ID: carID }, authAction, entityData); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: userToken, - action: authAction, entity: Entity.CAR, - module: MODULE_NAME, method: 'checkAndGetCarAuthorization', - value: carID - }); - } // Get Car const car = await CarStorage.getCar(tenant, carID, { ...additionalFilters, - ...authorizationFilter.filters + ...authorizations.filters }, - applyProjectFields ? authorizationFilter.projectFields : null + applyProjectFields ? authorizations.projectFields : null ); UtilsService.assertObjectExists(action, car, `Car ID '${carID}' does not exist`, MODULE_NAME, 'checkAndGetCarAuthorization', userToken); // Assign projected fields - if (authorizationFilter.projectFields) { - car.projectFields = authorizationFilter.projectFields; + if (authorizations.projectFields) { + car.projectFields = authorizations.projectFields; } // Assign Metadata - if (authorizationFilter.metadata) { - car.metadata = authorizationFilter.metadata; + if (authorizations.metadata) { + car.metadata = authorizations.metadata; } // Add Actions - await AuthorizationService.addCarAuthorizations(tenant, userToken, car, authorizationFilter); + await AuthorizationService.addCarAuthorizations(tenant, userToken, car, authorizations); const authorized = AuthorizationService.canPerformAction(car, authAction); if (!authorized) { throw new AppAuthError({ @@ -800,38 +682,29 @@ export default class UtilsService { // Check mandatory fields UtilsService.assertIdIsProvided(action, carCatalogID, MODULE_NAME, 'checkAndGetCarCatalogAuthorization', userToken); // Get dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetCarCatalogAuthorizations( + const authorizations = await AuthorizationService.checkAndGetCarCatalogAuthorizations( tenant, userToken, { ID: carCatalogID }, authAction, entityData); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: userToken, - action: authAction, entity: Entity.CAR_CATALOG, - module: MODULE_NAME, method: 'checkAndGetCarCatalogAuthorization', - value: carCatalogID.toString() - }); - } // Get the car const carCatalog = await CarStorage.getCarCatalog(carCatalogID, { ...additionalFilters, - ...authorizationFilter.filters + ...authorizations.filters }, - applyProjectFields ? authorizationFilter.projectFields : null + applyProjectFields ? authorizations.projectFields : null ); // Check it exists UtilsService.assertObjectExists(action, carCatalog, `Car Catalog ID '${carCatalogID}' does not exist`, MODULE_NAME, 'checkAndGetCarCatalogAuthorization', userToken); // Assign projected fields - if (authorizationFilter.projectFields) { - carCatalog.projectFields = authorizationFilter.projectFields; + if (authorizations.projectFields) { + carCatalog.projectFields = authorizations.projectFields; } // Assign Metadata - if (authorizationFilter.metadata) { - carCatalog.metadata = authorizationFilter.metadata; + if (authorizations.metadata) { + carCatalog.metadata = authorizations.metadata; } // Add actions - await AuthorizationService.addCarCatalogAuthorizations(tenant, userToken, carCatalog, authorizationFilter); + await AuthorizationService.addCarCatalogAuthorizations(tenant, userToken, carCatalog, authorizations); const authorized = AuthorizationService.canPerformAction(carCatalog, authAction); if (!authorized) { throw new AppAuthError({ @@ -845,6 +718,81 @@ export default class UtilsService { return carCatalog; } + // This function is tailored for SETTING authorization, do not use it for "general" entities ! + public static async checkAndGetBillingSettingAuthorization(tenant: Tenant, userToken: UserToken, billingSettingID: number, authAction: Action, + action: ServerAction, entityData?: EntityData, additionalFilters: Record = {}, applyProjectFields = false): Promise { + // Get dynamic auth + const authorizations = await AuthorizationService.checkAndGetSettingAuthorizations(tenant, userToken, authAction, entityData); + // Get the entity from storage + const billingSetting = await SettingStorage.getBillingSetting( + tenant, + applyProjectFields ? authorizations.projectFields : null + ); + // Check it exists + UtilsService.assertObjectExists(action, billingSetting, `Billing setting for tenantID '${tenant.id}' does not exist`, + MODULE_NAME, 'checkAndGetBillingSettingAuthorization', userToken); + // Assign projected fields + if (applyProjectFields && authorizations.projectFields) { + billingSetting.projectFields = authorizations.projectFields; + } + // Assign Metadata + if (authorizations.metadata) { + billingSetting.metadata = authorizations.metadata; + } + // Add actions + await AuthorizationService.addSettingAuthorizations(tenant, userToken, billingSetting, authorizations); + const authorized = AuthorizationService.canPerformAction(billingSetting, authAction); + if (!authorized) { + throw new AppAuthError({ + errorCode: HTTPAuthError.FORBIDDEN, + user: userToken, + action: authAction, entity: Entity.SETTING, + module: MODULE_NAME, method: 'checkAndGetBillingSettingAuthorization', + }); + } + return billingSetting; + } + + public static async checkAndGetInvoiceAuthorization(tenant: Tenant, userToken: UserToken, invoiceID: string, authAction: Action, + action: ServerAction, entityData?: EntityData, additionalFilters: Record = {}, applyProjectFields = false): Promise { + // Check mandatory fields + UtilsService.assertIdIsProvided(action, invoiceID, MODULE_NAME, 'checkAndGetInvoiceAuthorization', userToken); + // Get dynamic auth + const authorizations = await AuthorizationService.checkAndGetInvoiceAuthorizations( + tenant, userToken, { ID: invoiceID }, authAction, entityData); + // Get Invoice + const invoice = await BillingStorage.getInvoice(tenant, invoiceID, + { + ...additionalFilters, + ...authorizations.filters + }, + applyProjectFields ? authorizations.projectFields : null + ); + UtilsService.assertObjectExists(action, invoice, `Invoice ID '${invoiceID}' does not exist`, + MODULE_NAME, 'checkAndGetInvoiceAuthorization', userToken); + // Assign projected fields + if (authorizations.projectFields && applyProjectFields) { + invoice.projectFields = authorizations.projectFields; + } + // Assign Metadata + if (authorizations.metadata) { + invoice.metadata = authorizations.metadata; + } + // Add Actions + await AuthorizationService.addInvoiceAuthorizations(tenant, userToken, invoice, authorizations); + const authorized = AuthorizationService.canPerformAction(invoice, authAction); + if (!authorized) { + throw new AppAuthError({ + errorCode: HTTPAuthError.FORBIDDEN, + user: userToken, + action: authAction, entity: Entity.INVOICE, + module: MODULE_NAME, method: 'checkAndGetInvoiceAuthorization', + value: invoiceID + }); + } + return invoice; + } + public static async checkAndGetTagAuthorization(tenant: Tenant, userToken:UserToken, tagID: string, authAction: Action, action: ServerAction, entityData?: EntityData, additionalFilters: Record = {}, applyProjectFields = false): Promise { return UtilsService.checkAndGetTagByXXXAuthorization(tenant, userToken, tagID, TagStorage.getTag.bind(this), @@ -922,109 +870,6 @@ export default class UtilsService { } } - public static checkIfOCPIEndpointValid(ocpiEndpoint: Partial, req: Request): void { - if (req.method !== 'POST' && !ocpiEndpoint.id) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'The OCPI Endpoint ID is mandatory', - module: MODULE_NAME, - method: 'checkIfOCPIEndpointValid' - }); - } - if (!ocpiEndpoint.name) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'The OCPI Endpoint name is mandatory', - module: MODULE_NAME, - method: 'checkIfOCPIEndpointValid', - user: req.user.id - }); - } - if (!ocpiEndpoint.role) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'The OCPI Endpoint role is mandatory', - module: MODULE_NAME, - method: 'checkIfOCPIEndpointValid', - user: req.user.id - }); - } - if (!ocpiEndpoint.baseUrl) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'The OCPI Endpoint base URL is mandatory', - module: MODULE_NAME, - method: 'checkIfOCPIEndpointValid', - user: req.user.id - }); - } - if (ocpiEndpoint.countryCode && !countries.isValid(ocpiEndpoint.countryCode)) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: `The OCPI Endpoint ${ocpiEndpoint.countryCode} country code provided is invalid`, - module: MODULE_NAME, - method: 'checkIfOCPIEndpointValid', - user: req.user.id - }); - } - if (!ocpiEndpoint.localToken) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'The OCPI Endpoint local token is mandatory', - module: MODULE_NAME, - method: 'checkIfOCPIEndpointValid', - user: req.user.id - }); - } - if (!ocpiEndpoint.token) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'The OCPI Endpoint token is mandatory', - module: MODULE_NAME, - method: 'checkIfOCPIEndpointValid', - user: req.user.id - }); - } - } - - public static checkIfOICPEndpointValid(oicpEndpoint: Partial, req: Request): void { - if (req.method !== 'POST' && !oicpEndpoint.id) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'The OICP Endpoint ID is mandatory', - module: MODULE_NAME, - method: 'checkIfOICPEndpointValid' - }); - } - if (!oicpEndpoint.name) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'The OICP Endpoint name is mandatory', - module: MODULE_NAME, - method: 'checkIfOICPEndpointValid', - user: req.user.id - }); - } - if (!oicpEndpoint.role) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'The OICP Endpoint role is mandatory', - module: MODULE_NAME, - method: 'checkIfOICPEndpointValid', - user: req.user.id - }); - } - if (!oicpEndpoint.baseUrl) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'The OICP Endpoint base URL is mandatory', - module: MODULE_NAME, - method: 'checkIfOICPEndpointValid', - user: req.user.id - }); - } - } - public static httpSortFieldsToMongoDB(httpSortFields: string): any { // Exist? if (httpSortFields) { @@ -1160,61 +1005,6 @@ export default class UtilsService { public static checkIfChargingProfileIsValid(chargingStation: ChargingStation, chargePoint: ChargePoint, filteredRequest: ChargingProfile, req: Request): void { - if (req.method !== 'POST' && !filteredRequest.id) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'The Charging Profile ID is mandatory', - module: MODULE_NAME, - method: 'checkIfChargingProfileIsValid' - }); - } - if (!Utils.objectHasProperty(filteredRequest, 'chargingStationID')) { - throw new AppError({ - action: ServerAction.CHARGING_PROFILE_UPDATE, - errorCode: HTTPError.GENERAL_ERROR, - message: 'Charging Station ID is mandatory', - module: MODULE_NAME, method: 'checkIfChargingProfileIsValid', - user: req.user.id - }); - } - if (!Utils.objectHasProperty(filteredRequest, 'connectorID')) { - throw new AppError({ - action: ServerAction.CHARGING_PROFILE_UPDATE, - errorCode: HTTPError.GENERAL_ERROR, - message: 'Connector ID is mandatory', - module: MODULE_NAME, method: 'checkIfChargingProfileIsValid', - user: req.user.id - }); - } - if (!filteredRequest.profile) { - throw new AppError({ - action: ServerAction.CHARGING_PROFILE_UPDATE, - errorCode: HTTPError.GENERAL_ERROR, - message: 'Charging Profile is mandatory', - module: MODULE_NAME, method: 'checkIfChargingProfileIsValid', - user: req.user.id - }); - } - if (!filteredRequest.profile.chargingProfileId || !filteredRequest.profile.stackLevel || - !filteredRequest.profile.chargingProfilePurpose || !filteredRequest.profile.chargingProfileKind || - !filteredRequest.profile.chargingSchedule) { - throw new AppError({ - action: ServerAction.CHARGING_PROFILE_UPDATE, - errorCode: HTTPError.GENERAL_ERROR, - message: 'Invalid Charging Profile', - module: MODULE_NAME, method: 'checkIfChargingProfileIsValid', - user: req.user.id - }); - } - if (!filteredRequest.profile.chargingSchedule.chargingSchedulePeriod) { - throw new AppError({ - action: ServerAction.CHARGING_PROFILE_UPDATE, - errorCode: HTTPError.GENERAL_ERROR, - message: 'Invalid Charging Profile\'s Schedule', - module: MODULE_NAME, method: 'checkIfChargingProfileIsValid', - user: req.user.id - }); - } if (filteredRequest.profile.chargingSchedule.chargingSchedulePeriod.length === 0) { throw new AppError({ action: ServerAction.CHARGING_PROFILE_UPDATE, @@ -1343,66 +1133,7 @@ export default class UtilsService { } } - public static checkIfSiteValid(site: Partial, req: Request): void { - if (req.method !== 'POST' && !site.id) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Site ID is mandatory', - module: MODULE_NAME, method: 'checkIfSiteValid', - user: req.user.id - }); - } - if (!site.name) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Site Name is mandatory', - module: MODULE_NAME, method: 'checkIfSiteValid', - user: req.user.id - }); - } - if (!site.companyID) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Company ID is mandatory for the Site', - module: MODULE_NAME, method: 'checkIfSiteValid', - user: req.user.id - }); - } - } - public static checkIfTenantValid(tenant: Partial, req: Request): void { - if (req.method !== 'POST' && !tenant.id) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Tenant ID is mandatory', - module: MODULE_NAME, method: 'checkIfTenantValid', - user: req.user.id - }); - } - if (!tenant.name) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Tenant Name is mandatory', - module: MODULE_NAME, method: 'checkIfTenantValid', - user: req.user.id - }); - } - if (!tenant.components) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Tenant Components is mandatory', - module: MODULE_NAME, method: 'checkIfTenantValid', - user: req.user.id - }); - } - if (!tenant.components) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Tenant Components is mandatory', - module: MODULE_NAME, method: 'checkIfTenantValid', - user: req.user.id - }); - } if (tenant.components.oicp?.active && tenant.components.ocpi?.active) { throw new AppError({ errorCode: HTTPError.GENERAL_ERROR, @@ -1453,182 +1184,6 @@ export default class UtilsService { } } - public static checkIfSiteAreaValid(siteArea: Partial, req: Request): void { - if (req.method !== 'POST' && !siteArea.id) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Site Area ID is mandatory', - module: MODULE_NAME, method: 'checkIfSiteAreaValid', - user: req.user.id - }); - } - if (!siteArea.name) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Site Area name is mandatory', - module: MODULE_NAME, method: 'checkIfSiteAreaValid', - user: req.user.id - }); - } - if (!siteArea.siteID) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Site ID is mandatory', - module: MODULE_NAME, method: 'checkIfSiteAreaValid', - user: req.user.id - }); - } - // Power - if (siteArea.maximumPower <= 0) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: `Site maximum power must be a positive number but got ${siteArea.maximumPower} kW`, - module: MODULE_NAME, method: 'checkIfSiteAreaValid', - user: req.user.id - }); - } - if (siteArea.voltage !== Voltage.VOLTAGE_230 && siteArea.voltage !== Voltage.VOLTAGE_110) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: `Site voltage must be either 110V or 230V but got ${siteArea.voltage as number}V`, - module: MODULE_NAME, method: 'checkIfSiteAreaValid', - user: req.user.id - }); - } - if (siteArea.numberOfPhases !== 1 && siteArea.numberOfPhases !== 3) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: `Site area number of phases must be either 1 or 3 but got ${siteArea.numberOfPhases}`, - module: MODULE_NAME, method: 'checkIfSiteAreaValid', - user: req.user.id - }); - } - } - - public static checkIfPricingDefinitionValid(pricing: Partial, req: Request): void { - if (req.method !== 'POST' && !pricing.id) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Pricing ID is mandatory', - module: MODULE_NAME, method: 'checkIfPricingDefinitionValid', - user: req.user.id - }); - } - if (!pricing.dimensions) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Pricing Dimensions are mandatory', - module: MODULE_NAME, method: 'checkIfPricingDefinitionValid', - user: req.user.id - }); - } - } - - public static checkIfAssetValid(asset: Partial, req: Request): void { - if (req.method !== 'POST' && !asset.id) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Asset ID is mandatory', - module: MODULE_NAME, method: 'checkIfAssetValid', - user: req.user.id - }); - } - if (!asset.name) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Asset Name is mandatory', - module: MODULE_NAME, method: 'checkIfAssetValid', - user: req.user.id - }); - } - if (!asset.siteAreaID) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Asset Site Area is mandatory', - module: MODULE_NAME, method: 'checkIfAssetValid', - user: req.user.id - }); - } - if (!asset.assetType) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Asset type is mandatory', - module: MODULE_NAME, method: 'checkIfAssetValid', - user: req.user.id - }); - } - if (!(typeof asset.staticValueWatt === 'number')) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Fallback value must be of type number', - module: MODULE_NAME, method: 'checkIfAssetValid', - user: req.user.id - }); - } - if (Utils.objectHasProperty(asset, 'fluctuationPercent')) { - if (!(typeof asset.fluctuationPercent === 'number') || asset.fluctuationPercent < 0 || asset.fluctuationPercent > 100) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Fluctuation percentage should be between 0 and 100', - module: MODULE_NAME, method: 'checkIfAssetValid', - user: req.user.id - }); - } - } - if (asset.dynamicAsset) { - if (!asset.connectionID && !asset.usesPushAPI) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Asset connection is mandatory, if it is not using push API', - module: MODULE_NAME, method: 'checkIfAssetValid', - user: req.user.id - }); - } - if (!asset.meterID && !asset.usesPushAPI) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Asset meter ID is mandatory, if it is not using push API', - module: MODULE_NAME, method: 'checkIfAssetValid', - user: req.user.id - }); - } - } - } - - public static checkIfUserTagIsValid(tag: Partial, req: Request): void { - // Check RFID Card - if (!tag.id) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Tag ID is mandatory', - module: MODULE_NAME, method: 'checkIfUserTagIsValid', - user: req.user.id - }); - } - // Check badge visual ID - if (!tag.visualID) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Tag visual ID is mandatory', - module: MODULE_NAME, method: 'checkIfUserTagIsValid', - user: req.user.id - }); - } - // Check description - if (!tag.description) { - tag.description = `Tag ID '${tag.id}'`; - } - // Check user activation - if (!Utils.objectHasProperty(tag, 'active')) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Tag Active property is mandatory', - module: MODULE_NAME, method: 'checkIfUserTagIsValid', - user: req.user.id - }); - } - } - public static checkIfUserValid(filteredRequest: Partial, user: User, req: Request): void { const tenantID = req.user.tenantID; if (!tenantID) { @@ -1737,128 +1292,6 @@ export default class UtilsService { actionOnUser: filteredRequest.id }); } - if (filteredRequest.phone && !Utils.isPhoneValid(filteredRequest.phone)) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: `User Phone '${filteredRequest.phone}' is not valid`, - module: MODULE_NAME, - method: 'checkIfUserValid', - user: req.user.id, - actionOnUser: filteredRequest.id - }); - } - if (filteredRequest.mobile && !Utils.isPhoneValid(filteredRequest.mobile)) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'User Mobile is mandatory', - module: MODULE_NAME, - method: 'checkIfUserValid', - user: req.user.id, - actionOnUser: filteredRequest.id - }); - } - if (filteredRequest.plateID && !Utils.isPlateIDValid(filteredRequest.plateID)) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: `User Plate ID '${filteredRequest.plateID}' is not valid`, - module: MODULE_NAME, - method: 'checkIfUserValid', - user: req.user.id, - actionOnUser: filteredRequest.id - }); - } - } - - public static checkIfCarValid(car: Partial, req: Request): void { - if (req.method !== 'POST' && !car.id) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Car ID is mandatory', - module: MODULE_NAME, method: 'checkIfCarValid', - user: req.user.id - }); - } - if (!car.vin) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Vin Car is mandatory', - module: MODULE_NAME, method: 'checkIfCarValid', - user: req.user.id - }); - } - if (!car.licensePlate) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'License Plate is mandatory', - module: MODULE_NAME, method: 'checkIfCarValid', - user: req.user.id - }); - } - if (!Utils.isPlateIDValid(car.licensePlate)) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: `Car License Plate ID '${car.licensePlate}' is not valid`, - module: MODULE_NAME, method: 'checkIfCarValid', - user: req.user.id, - actionOnUser: car.id - }); - } - if (!car.carCatalogID) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Car Catalog ID is mandatory', - module: MODULE_NAME, method: 'checkIfCarValid', - user: req.user.id - }); - } - if (!car.type) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Car type is mandatory', - module: MODULE_NAME, method: 'checkIfCarValid', - user: req.user.id - }); - } - if (!car.converter) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Car Converter is mandatory', - module: MODULE_NAME, method: 'checkIfCarValid', - user: req.user.id - }); - } - if (!car.converter.amperagePerPhase) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Car Converter amperage per phase is mandatory', - module: MODULE_NAME, method: 'checkIfCarValid', - user: req.user.id - }); - } - if (!car.converter.numberOfPhases) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Car Converter number of phases is mandatory', - module: MODULE_NAME, method: 'checkIfCarValid', - user: req.user.id - }); - } - if (!car.converter.powerWatts) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Car Converter power is mandatory', - module: MODULE_NAME, method: 'checkIfCarValid', - user: req.user.id - }); - } - if (!car.converter.type) { - throw new AppError({ - errorCode: HTTPError.GENERAL_ERROR, - message: 'Car Converter type is mandatory', - module: MODULE_NAME, method: 'checkIfCarValid', - user: req.user.id - }); - } } // eslint-disable-next-line @typescript-eslint/ban-types @@ -1939,37 +1372,28 @@ export default class UtilsService { // Check mandatory fields UtilsService.assertIdIsProvided(action, id, MODULE_NAME, 'checkAndGetTagByXXXAuthorization', userToken); // Get dynamic auth - const authorizationFilter = await AuthorizationService.checkAndGetTagAuthorizations( + const authorizations = await AuthorizationService.checkAndGetTagAuthorizations( tenant, userToken, { ID: id }, authAction, entityData); - if (!authorizationFilter.authorized) { - throw new AppAuthError({ - errorCode: HTTPAuthError.FORBIDDEN, - user: userToken, - action: authAction, entity: Entity.TAG, - module: MODULE_NAME, method: 'checkAndGetTagByXXXAuthorization', - value: id - }); - } // Get the Tag & check it exists const tag = await getTagByXXX(tenant, id, { ...additionalFilters, - ...authorizationFilter.filters + ...authorizations.filters }, - applyProjectFields ? authorizationFilter.projectFields : null + applyProjectFields ? authorizations.projectFields : null ); UtilsService.assertObjectExists(action, tag, `Tag ID '${id}' does not exist`, MODULE_NAME, 'handleGetTag', userToken); // Assign projected fields - if (authorizationFilter.projectFields) { - tag.projectFields = authorizationFilter.projectFields; + if (authorizations.projectFields) { + tag.projectFields = authorizations.projectFields; } // Assign Metadata - if (authorizationFilter.metadata) { - tag.metadata = authorizationFilter.metadata; + if (authorizations.metadata) { + tag.metadata = authorizations.metadata; } // Add actions - await AuthorizationService.addTagAuthorizations(tenant, userToken, tag, authorizationFilter); + await AuthorizationService.addTagAuthorizations(tenant, userToken, tag, authorizations); const authorized = AuthorizationService.canPerformAction(tag, authAction); if (!authorized) { throw new AppAuthError({ diff --git a/src/server/rest/v1/validator/LogValidator.ts b/src/server/rest/v1/validator/LogValidator.ts new file mode 100644 index 0000000000..d4597ef521 --- /dev/null +++ b/src/server/rest/v1/validator/LogValidator.ts @@ -0,0 +1,31 @@ +import { HttpLogRequest, HttpLogsRequest } from '../../../../types/requests/HttpLogRequest'; + +import Schema from '../../../../types/validator/Schema'; +import SchemaValidator from '../../../../validator/SchemaValidator'; +import fs from 'fs'; +import global from '../../../../types/GlobalType'; + +export default class LogValidator extends SchemaValidator { + private static instance: LogValidator|null = null; + private logsGet: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/log/logs-get.json`, 'utf8')); + private logGet: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/log/log-get.json`, 'utf8')); + + private constructor() { + super('LogValidator'); + } + + public static getInstance(): LogValidator { + if (!LogValidator.instance) { + LogValidator.instance = new LogValidator(); + } + return LogValidator.instance; + } + + public validateLogsGetReq(data: Record): HttpLogsRequest { + return this.validate(this.logsGet, data); + } + + public validateLogGetReq(data: Record): HttpLogRequest { + return this.validate(this.logGet, data); + } +} diff --git a/src/server/rest/v1/validator/LoggingValidator.ts b/src/server/rest/v1/validator/LoggingValidator.ts deleted file mode 100644 index cd821f27e7..0000000000 --- a/src/server/rest/v1/validator/LoggingValidator.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { HttpLogRequest, HttpLogsRequest } from '../../../../types/requests/HttpLoggingRequest'; - -import Schema from '../../../../types/validator/Schema'; -import SchemaValidator from '../../../../validator/SchemaValidator'; -import fs from 'fs'; -import global from '../../../../types/GlobalType'; - -export default class LoggingValidator extends SchemaValidator { - private static instance: LoggingValidator|null = null; - private loggingsGet: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/logging/loggings-get.json`, 'utf8')); - private loggingGet: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/logging/logging-get.json`, 'utf8')); - - private constructor() { - super('LoggingValidator'); - } - - public static getInstance(): LoggingValidator { - if (!LoggingValidator.instance) { - LoggingValidator.instance = new LoggingValidator(); - } - return LoggingValidator.instance; - } - - public validateLoggingsGetReq(data: Record): HttpLogsRequest { - return this.validate(this.loggingsGet, data); - } - - public validateLoggingGetReq(data: Record): HttpLogRequest { - return this.validate(this.loggingGet, data); - } -} diff --git a/src/storage/mongodb/BillingStorage.ts b/src/storage/mongodb/BillingStorage.ts index 62b67c87ef..b0c0bcbedd 100644 --- a/src/storage/mongodb/BillingStorage.ts +++ b/src/storage/mongodb/BillingStorage.ts @@ -13,9 +13,9 @@ import Utils from '../../utils/Utils'; const MODULE_NAME = 'BillingStorage'; export default class BillingStorage { - public static async getInvoice(tenant: Tenant, id: string = Constants.UNKNOWN_OBJECT_ID, projectFields?: string[]): Promise { + public static async getInvoice(tenant: Tenant, id: string = Constants.UNKNOWN_OBJECT_ID, params: { userIDs?: string[] } = {}, projectFields?: string[]): Promise { const invoicesMDB = await BillingStorage.getInvoices(tenant, { - invoiceIDs: [id] + invoiceIDs: [id], userIDs: params.userIDs }, Constants.DB_PARAMS_SINGLE_RECORD, projectFields); return invoicesMDB.count === 1 ? invoicesMDB.result[0] : null; } diff --git a/src/storage/mongodb/ConsumptionStorage.ts b/src/storage/mongodb/ConsumptionStorage.ts index fba88ef31d..ca9d3309d5 100644 --- a/src/storage/mongodb/ConsumptionStorage.ts +++ b/src/storage/mongodb/ConsumptionStorage.ts @@ -218,6 +218,7 @@ export default class ConsumptionStorage { minute: { '$minute': '$startedAt' }, assetID: '$assetID', chargeBoxID: '$chargeBoxID', + connectorID: '$connectorId', }, InstantWattsT: { $avg: '$instantWatts' }, InstantAmpsT: { $avg: '$instantAmps' }, @@ -245,7 +246,11 @@ export default class ConsumptionStorage { }] }, '_id.chargingStation': { - $ne: ['$_id.chargeBoxID', null] + $and: [{ + $ne: ['$_id.chargeBoxID', null] + },{ + $ne: ['$_id.connectorID', null] + }] } } }); @@ -570,66 +575,95 @@ export default class ConsumptionStorage { transactionId: Utils.convertToInt(params.transactionId) } }); - aggregation.push({ - $addFields: { roundedInstantPower: { $round: [{ $divide: ['$instantWatts', 100] }] } } - }); - // Triming excess values + // Group by aggregation.push({ $group: { _id: { - roundedInstantPower: '$roundedInstantPower', - limitWatts: '$limitWatts' + year: { '$year': '$endedAt' }, + month: { '$month': '$endedAt' }, + day: { '$dayOfMonth': '$endedAt' }, + hour: { '$hour': '$endedAt' }, + minute: { '$minute': '$endedAt' } }, - consumptions: { $push: '$$ROOT' } + consumptions :{ + $first: { + 'cumulatedConsumptionWh': '$cumulatedConsumptionWh', + 'cumulatedConsumptionAmps': '$cumulatedConsumptionAmps', + 'cumulatedAmount': '$cumulatedAmount', + 'stateOfCharge': '$stateOfCharge', + 'limitWatts': '$limitWatts', + 'limitAmps': '$limitAmps', + 'instantVoltsDC': '$instantVoltsDC', + 'instantVolts': '$instantVolts', + 'instantVoltsL1': '$instantVoltsL1', + 'instantVoltsL2': '$instantVoltsL2', + 'instantVoltsL3': '$instantVoltsL3', + 'instantWattsDC': '$instantWattsDC', + 'instantWatts': '$instantWatts', + 'instantWattsL1': '$instantWattsL1', + 'instantWattsL2': '$instantWattsL2', + 'instantWattsL3': '$instantWattsL3', + 'instantAmpsDC': '$instantAmpsDC', + 'instantAmps': '$instantAmps', + 'instantAmpsL1': '$instantAmpsL1', + 'instantAmpsL2': '$instantAmpsL2', + 'instantAmpsL3': '$instantAmpsL3', + 'startedAt': '$startedAt', + 'endedAt': '$endedAt', + } + } } }); - // Convert Object ID to string - DatabaseUtils.pushConvertObjectIDToString(aggregation, 'siteID'); - DatabaseUtils.pushConvertObjectIDToString(aggregation, 'siteAreaID'); - DatabaseUtils.pushConvertObjectIDToString(aggregation, 'userID'); + // Rename fields to original fields aggregation.push({ - $sort: { 'consumptions.startedAt': 1 } + $addFields: { + 'cumulatedConsumptionWh': '$consumptions.cumulatedConsumptionWh', + 'cumulatedConsumptionAmps': '$consumptions.cumulatedConsumptionAmps', + 'cumulatedAmount': '$consumptions.cumulatedAmount', + 'stateOfCharge': '$consumptions.stateOfCharge', + 'limitWatts': '$consumptions.limitWatts', + 'limitAmps': '$consumptions.limitAmps', + 'instantVoltsDC': '$consumptions.instantVoltsDC', + 'instantVolts': '$consumptions.instantVolts', + 'instantVoltsL1': '$consumptions.instantVoltsL1', + 'instantVoltsL2': '$consumptions.instantVoltsL2', + 'instantVoltsL3': '$consumptions.instantVoltsL3', + 'instantWattsDC': '$consumptions.instantWattsDC', + 'instantWatts': '$consumptions.instantWatts', + 'instantWattsL1': '$consumptions.instantWattsL1', + 'instantWattsL2': '$consumptions.instantWattsL2', + 'instantWattsL3': '$consumptions.instantWattsL3', + 'instantAmpsDC': '$consumptions.instantAmpsDC', + 'instantAmps': '$consumptions.instantAmps', + 'instantAmpsL1': '$consumptions.instantAmpsL1', + 'instantAmpsL2': '$consumptions.instantAmpsL2', + 'instantAmpsL3': '$consumptions.instantAmpsL3', + 'startedAt': '$consumptions.startedAt', + 'endedAt': '$consumptions.endedAt', + } + }); + // Remove _id from projected fields + aggregation.push({ + $project: { + _id: 0, + consumptions: 0, + } }); // Project DatabaseUtils.projectFields(aggregation, projectFields); + // Sort + aggregation.push({ + $sort: { + 'endedAt': 1, + } + }); // Read DB - const consumptionsMDB = await global.database.getCollection(tenant.id, 'consumptions') - .aggregate(aggregation, DatabaseUtils.buildAggregateOptions()) + const consumptionsMDB = await global.database.getCollection(tenant.id, 'consumptions') + .aggregate(aggregation, DatabaseUtils.buildAggregateOptions()) .toArray(); - // TODO: Handle this coding into MongoDB request - const consumptions: Consumption[] = []; - for (const consumptionMDB of consumptionsMDB) { - let lastConsumption: Consumption = null; - let lastConsumtionRemoved = false; - // Simplify grouped consumption - for (let i = 0; i <= consumptionMDB.consumptions.length - 3; i++) { - if (!lastConsumption) { - lastConsumption = consumptionMDB.consumptions[i]; - } - if (lastConsumption.endedAt && consumptionMDB.consumptions[i + 1].startedAt && - lastConsumption.endedAt.getTime() === consumptionMDB.consumptions[i + 1].startedAt.getTime()) { - // Remove - lastConsumption = consumptionMDB.consumptions[i + 1]; - consumptionMDB.consumptions.splice(i + 1, 1); - lastConsumtionRemoved = true; - i--; - } else { - // Insert the last consumption before it changes - if (lastConsumtionRemoved) { - consumptionMDB.consumptions.splice(i, 0, lastConsumption); - lastConsumtionRemoved = false; - i++; - } - lastConsumption = consumptionMDB.consumptions[i + 1]; - } - } - // Unwind - for (const consumption of consumptionMDB.consumptions) { - consumptions.push(consumption); - } - } - // Sort - consumptions.sort((cons1, cons2) => cons1.endedAt.getTime() - cons2.endedAt.getTime()); + const lastElement = consumptionsMDB.pop(); + const consumptions = consumptionsMDB.filter((elem, index) => index % 5 === 0 ? true : false); + consumptions.push(lastElement); await Logging.traceDatabaseRequestEnd(tenant, MODULE_NAME, 'getOptimizedTransactionConsumptions', startTime, aggregation, consumptions); return consumptions; } diff --git a/src/storage/mongodb/LoggingStorage.ts b/src/storage/mongodb/LogStorage.ts similarity index 93% rename from src/storage/mongodb/LoggingStorage.ts rename to src/storage/mongodb/LogStorage.ts index 197bed16b7..1135378572 100644 --- a/src/storage/mongodb/LoggingStorage.ts +++ b/src/storage/mongodb/LogStorage.ts @@ -1,5 +1,5 @@ import { DataResult, DeletedResult } from '../../types/DataResult'; -import global, { DatabaseCount, FilterParams } from './../../types/GlobalType'; +import global, { DatabaseCount, FilterParams } from '../../types/GlobalType'; import Constants from '../../utils/Constants'; import DatabaseUtils from './DatabaseUtils'; @@ -9,7 +9,7 @@ import { ServerType } from '../../types/Server'; import Tenant from '../../types/Tenant'; import Utils from '../../utils/Utils'; -export default class LoggingStorage { +export default class LogStorage { public static async deleteLogs(tenant: Tenant, deleteUpToDate: Date): Promise { DatabaseUtils.checkTenantObject(tenant); // Build filter @@ -56,7 +56,7 @@ export default class LoggingStorage { public static async getLog(tenant: Tenant, id: string = Constants.UNKNOWN_OBJECT_ID, params: { siteIDs?: string[]; } = {}, projectFields: string[]): Promise { - const logsMDB = await LoggingStorage.getLogs(tenant, { + const logsMDB = await LogStorage.getLogs(tenant, { logIDs: [id], siteIDs: params.siteIDs, }, Constants.DB_PARAMS_SINGLE_RECORD, projectFields); @@ -150,13 +150,13 @@ export default class LoggingStorage { // Always limit the nbr of record to avoid perfs issues aggregation.push({ $limit: Constants.DB_RECORD_COUNT_CEIL }); } - const loggingsCountMDB = await global.database.getCollection(tenant.id, 'logs') + const logsCountMDB = await global.database.getCollection(tenant.id, 'logs') .aggregate([...aggregation, { $count: 'count' }]) .toArray() as DatabaseCount[]; // Check if only the total count is requested if (dbParams.onlyRecordCount) { return { - count: (loggingsCountMDB.length > 0 ? loggingsCountMDB[0].count : 0), + count: (logsCountMDB.length > 0 ? logsCountMDB[0].count : 0), result: [] }; } @@ -211,12 +211,12 @@ export default class LoggingStorage { // Project DatabaseUtils.projectFields(aggregation, projectFields); // Read DB - const loggingsMDB = await global.database.getCollection(tenant.id, 'logs') + const logsMDB = await global.database.getCollection(tenant.id, 'logs') .aggregate(aggregation, DatabaseUtils.buildAggregateOptions()) .toArray() as Log[]; return { - count: DatabaseUtils.getCountFromDatabaseCount(loggingsCountMDB[0]), - result: loggingsMDB + count: DatabaseUtils.getCountFromDatabaseCount(logsCountMDB[0]), + result: logsMDB }; } } diff --git a/src/storage/mongodb/MongoDBStorage.ts b/src/storage/mongodb/MongoDBStorage.ts index d6115bcf31..c635731367 100644 --- a/src/storage/mongodb/MongoDBStorage.ts +++ b/src/storage/mongodb/MongoDBStorage.ts @@ -111,10 +111,6 @@ export default class MongoDBStorage { await this.handleIndexesInCollection(tenantID, 'importedusers', [ { fields: { email: 1 }, options: { unique: true } } ]); - await this.handleIndexesInCollection(tenantID, 'eulas'); - // Assets - await this.handleIndexesInCollection(tenantID, 'assets', [ - ]); // Invoices await this.handleIndexesInCollection(tenantID, 'invoices', [ { fields: { invoiceID: 1 }, options: { unique: true } }, @@ -144,8 +140,8 @@ export default class MongoDBStorage { await this.handleIndexesInCollection(tenantID, 'tags', [ { fields: { visualID: 1 }, options: { unique: true } }, { fields: { issuer: 1, createdOn: 1 } }, + { fields: { userID: 1 } }, { fields: { createdOn: 1 } }, - { fields: { userID: 1, issuer: 1 } }, { fields: { _id: 'text', description: 'text', visualID: 'text' } }, ]); // Tags Import @@ -266,7 +262,7 @@ export default class MongoDBStorage { const mongoDBClient = await MongoClient.connect( mongoUrl, { - minPoolSize: Math.floor(this.dbConfig.poolSize / 4), + minPoolSize: Math.floor(this.dbConfig.poolSize / 2), maxPoolSize: this.dbConfig.poolSize, loggerLevel: this.dbConfig.debug ? 'debug' : null, readPreference: this.dbConfig.readPreference ? this.dbConfig.readPreference as ReadPreferenceMode : ReadPreferenceMode.secondaryPreferred diff --git a/src/storage/mongodb/SettingStorage.ts b/src/storage/mongodb/SettingStorage.ts index d57aa2c5c6..366cae1ca2 100644 --- a/src/storage/mongodb/SettingStorage.ts +++ b/src/storage/mongodb/SettingStorage.ts @@ -436,9 +436,9 @@ export default class SettingStorage { await SettingStorage.saveSettings(tenant, settingsToSave); } - public static async getBillingSetting(tenant: Tenant): Promise { + public static async getBillingSetting(tenant: Tenant, projectedFields?: string[]): Promise { // Get BILLING Settings by Identifier - const setting = await SettingStorage.getSettingByIdentifier(tenant, TenantComponents.BILLING); + const setting = await SettingStorage.getSettingByIdentifier(tenant, TenantComponents.BILLING, projectedFields); if (setting) { const { id, backupSensitiveData, category } = setting; const { createdBy, createdOn, lastChangedBy, lastChangedOn } = setting; diff --git a/src/storage/mongodb/SiteAreaStorage.ts b/src/storage/mongodb/SiteAreaStorage.ts index 0ec7582916..bb29f2e6db 100644 --- a/src/storage/mongodb/SiteAreaStorage.ts +++ b/src/storage/mongodb/SiteAreaStorage.ts @@ -32,23 +32,21 @@ export default class SiteAreaStorage { return updated; } - public static async addAssetsToSiteArea(tenant: Tenant, siteArea: SiteArea, assetIDs: string[]): Promise { + public static async addAssetsToSiteArea(tenant: Tenant, siteAreaID: string, siteID: string, companyID: string, assetIDs: string[]): Promise { const startTime = Logging.traceDatabaseRequestStart(); DatabaseUtils.checkTenantObject(tenant); - // Site Area provided? - if (siteArea) { - // At least one Asset - if (assetIDs && assetIDs.length > 0) { - // Update all assets - await global.database.getCollection(tenant.id, 'assets').updateMany( - { '_id': { $in: assetIDs.map((assetID) => DatabaseUtils.convertToObjectID(assetID)) } }, - { - $set: { - siteAreaID: DatabaseUtils.convertToObjectID(siteArea.id), - siteID: DatabaseUtils.convertToObjectID(siteArea.siteID) - } - }); - } + // At least one Asset + if (!Utils.isEmptyArray(assetIDs)) { + // Update all assets + await global.database.getCollection(tenant.id, 'assets').updateMany( + { '_id': { $in: assetIDs.map((assetID) => DatabaseUtils.convertToObjectID(assetID)) } }, + { + $set: { + siteAreaID: DatabaseUtils.convertToObjectID(siteAreaID), + siteID: DatabaseUtils.convertToObjectID(siteID), + companyID: DatabaseUtils.convertToObjectID(companyID) + } + }); } await Logging.traceDatabaseRequestEnd(tenant, MODULE_NAME, 'addAssetsToSiteArea', startTime, assetIDs); } @@ -66,7 +64,8 @@ export default class SiteAreaStorage { { $set: { siteAreaID: null, - siteID: null + siteID: null, + companyID: null } }); } @@ -386,24 +385,21 @@ export default class SiteAreaStorage { }; } - public static async addChargingStationsToSiteArea(tenant: Tenant, siteArea: SiteArea, chargingStationIDs: string[]): Promise { + public static async addChargingStationsToSiteArea(tenant: Tenant, siteAreaID: string, siteID: string, companyID: string, chargingStationIDs: string[]): Promise { const startTime = Logging.traceDatabaseRequestStart(); DatabaseUtils.checkTenantObject(tenant); - // Site provided? - if (siteArea) { - // At least one ChargingStation - if (chargingStationIDs && chargingStationIDs.length > 0) { - // Update all chargers - await global.database.getCollection(tenant.id, 'chargingstations').updateMany( - { '_id': { $in: chargingStationIDs } }, - { - $set: { - companyID: DatabaseUtils.convertToObjectID(siteArea.site?.companyID), - siteID: DatabaseUtils.convertToObjectID(siteArea.siteID), - siteAreaID: DatabaseUtils.convertToObjectID(siteArea.id), - } - }); - } + // At least one ChargingStation + if (!Utils.isEmptyArray(chargingStationIDs)) { + // Update all chargers + await global.database.getCollection(tenant.id, 'chargingstations').updateMany( + { '_id': { $in: chargingStationIDs } }, + { + $set: { + siteAreaID: DatabaseUtils.convertToObjectID(siteAreaID), + siteID: DatabaseUtils.convertToObjectID(siteID), + companyID: DatabaseUtils.convertToObjectID(companyID), + } + }); } await Logging.traceDatabaseRequestEnd(tenant, MODULE_NAME, 'addChargingStationsToSiteArea', startTime, chargingStationIDs); } diff --git a/src/types/Authorization.ts b/src/types/Authorization.ts index 67ec3570e8..151ec6de5e 100644 --- a/src/types/Authorization.ts +++ b/src/types/Authorization.ts @@ -224,6 +224,10 @@ export interface SiteAuthorizationActions extends AuthorizationActions { canMaintainPricingDefinitions?: boolean; } +export interface BillingInvoiceAuthorizationActions extends AuthorizationActions { + canDownload?:boolean; +} + export enum DynamicAuthorizationFilterName { ASSIGNED_SITES_COMPANIES = 'AssignedSitesCompanies', SITES_ADMIN = 'SitesAdmin', diff --git a/src/types/Billing.ts b/src/types/Billing.ts index 59c722eb0b..d90f51ffb4 100644 --- a/src/types/Billing.ts +++ b/src/types/Billing.ts @@ -1,4 +1,7 @@ +import { AuthorizationActions, BillingInvoiceAuthorizationActions } from './Authorization'; + import { ActionsResponse } from './GlobalType'; +import CreatedUpdatedProps from './CreatedUpdatedProps'; import { PricedConsumptionData } from './Pricing'; import User from './User'; @@ -60,7 +63,7 @@ export interface BillingTax { percentage: number; } -export interface BillingInvoice { +export interface BillingInvoice extends CreatedUpdatedProps, BillingInvoiceAuthorizationActions { id: string; invoiceID: string; liveMode: boolean; @@ -112,7 +115,7 @@ export interface BillingOperationResult { internalData?: unknown // an object returned by the concrete implementation - e.g.: STRIPE } -export interface BillingPaymentMethod { +export interface BillingPaymentMethod extends AuthorizationActions { id: string; brand: string; expiringOn: Date; diff --git a/src/types/DataResult.ts b/src/types/DataResult.ts index 2c5ca7c865..0a9b8526b5 100644 --- a/src/types/DataResult.ts +++ b/src/types/DataResult.ts @@ -1,3 +1,4 @@ +import { BillingInvoice, BillingPaymentMethod } from './Billing'; import { Car, CarCatalog } from './Car'; import Transaction, { TransactionStats } from './Transaction'; @@ -81,6 +82,14 @@ export interface TransactionDataResult extends DataResult { stats: TransactionStats; } +export interface BillingInvoiceDataResult extends DataResult { + canListUsers?: boolean; +} + +export interface BillingPaymentMethodDataResult extends DataResult { + canCreate?: boolean; +} + export interface TransactionRefundDataResult { count: number; result: Transaction[]; diff --git a/src/types/GlobalType.ts b/src/types/GlobalType.ts index eb1439cfc6..ac3da7df56 100644 --- a/src/types/GlobalType.ts +++ b/src/types/GlobalType.ts @@ -1,3 +1,4 @@ +import { BillingInvoice, BillingPaymentMethod } from './Billing'; import { Car, CarCatalog } from './Car'; import ChargingStation from './ChargingStation'; @@ -8,6 +9,7 @@ import MongoDBStorage from '../storage/mongodb/MongoDBStorage'; import PricingDefinition from './Pricing'; import RegistrationToken from './RegistrationToken'; import { ServerType } from './Server'; +import { Setting } from './Setting'; import Site from './Site'; import SiteArea from './SiteArea'; import SoapOCPPServer from '../server/ocpp/soap/SoapOCPPServer'; @@ -74,7 +76,7 @@ export enum ImportStatus { ERROR = 'E', } -export type EntityData = Car|User|Company|Site|SiteArea|Tag|CarCatalog|ChargingStation|PricingDefinition|Log|RegistrationToken; +export type EntityData = Car|User|Company|Site|SiteArea|Tag|CarCatalog|ChargingStation|PricingDefinition|Log|RegistrationToken|BillingInvoice|BillingPaymentMethod|Setting; interface TSGlobal extends Global { database: MongoDBStorage; diff --git a/src/types/Locking.ts b/src/types/Locking.ts index b8d8e246cf..9ad01b6c58 100644 --- a/src/types/Locking.ts +++ b/src/types/Locking.ts @@ -20,7 +20,7 @@ export enum LockEntity { CHARGING_STATION = 'charging-station', SITE_AREA = 'site-area', USER = 'user', - LOGGING = 'logging', + LOG = 'log', PERFORMANCE = 'performance', TRANSACTION = 'transaction', CAR = 'car', diff --git a/src/types/Server.ts b/src/types/Server.ts index 7bfb1d3373..9b048443a2 100644 --- a/src/types/Server.ts +++ b/src/types/Server.ts @@ -70,9 +70,9 @@ export enum ServerAction { TRANSACTIONS_DELETE = 'TransactionsDelete', UPDATE_TRANSACTION = 'UpdateTransaction', - LOGGINGS = 'Loggings', - LOGGING = 'Logging', - LOGGINGS_EXPORT = 'LoggingsExport', + LOGS = 'Logs', + LOG = 'Log', + LOGS_EXPORT = 'LogsExport', CHARGING_STATIONS = 'ChargingStations', @@ -593,14 +593,13 @@ export enum RESTServerRoute { REST_CONNECTIONS = 'connections', REST_CONNECTION = 'connections/:id', - REST_LOGGINGS = 'loggings', - REST_LOGGING = 'loggings/:id', - REST_LOGGINGS_EXPORT = 'loggings/action/export', + REST_LOGS = 'logs', + REST_LOG = 'logs/:id', + REST_LOGS_EXPORT = 'logs/action/export', REST_NOTIFICATIONS = 'notifications', REST_NOTIFICATIONS_END_USER_REPORT_ERROR = 'notifications/action/end-user/report-error', - REST_OCPI_ENDPOINT_PING = 'ocpi/endpoints/:id/ping', REST_OCPI_ENDPOINT_CHECK_CDRS = 'ocpi/endpoints/:id/cdrs/check', REST_OCPI_ENDPOINT_CHECK_LOCATIONS = 'ocpi/endpoints/:id/locations/check', diff --git a/src/types/Setting.ts b/src/types/Setting.ts index b419fe379c..93aeacb322 100644 --- a/src/types/Setting.ts +++ b/src/types/Setting.ts @@ -1,3 +1,4 @@ +import { AuthorizationActions } from './Authorization'; import CreatedUpdatedProps from './CreatedUpdatedProps'; import { TenantComponents } from './Tenant'; @@ -21,7 +22,7 @@ export enum IntegrationSettings { STATISTICS = 'statistics' } -export interface Setting extends CreatedUpdatedProps { +export interface Setting extends AuthorizationActions, CreatedUpdatedProps { id?: string; identifier: TenantComponents | TechnicalSettings; sensitiveData?: string[]; diff --git a/src/types/configuration/Configuration.ts b/src/types/configuration/Configuration.ts index 88ab92fda8..c4fb34b331 100644 --- a/src/types/configuration/Configuration.ts +++ b/src/types/configuration/Configuration.ts @@ -14,7 +14,7 @@ import FirebaseConfiguration from './FirebaseConfiguration'; import HealthCheckConfiguration from './HealthCheckConfiguration'; import JsonEndpointConfiguration from './JsonEndpointConfiguration'; import LocalesConfiguration from './LocalesConfiguration'; -import LoggingConfiguration from './LoggingConfiguration'; +import LogConfiguration from './LogConfiguration'; import MigrationConfiguration from './MigrationConfiguration'; import MonitoringConfiguration from './MonitoringConfiguration'; import NotificationConfiguration from './NotificationConfiguration'; @@ -50,7 +50,7 @@ export interface Configuration { Locales?: LocalesConfiguration; Scheduler: SchedulerConfiguration; AsyncTask: AsyncTaskConfiguration; - Logging: LoggingConfiguration; + Logging: LogConfiguration; HealthCheck?: HealthCheckConfiguration; Migration?: MigrationConfiguration; EVDatabase?: EVDatabaseConfiguration; @@ -60,4 +60,4 @@ export interface Configuration { Monitoring?: MonitoringConfiguration; } -export type ConfigurationSection = CryptoConfiguration|CentralSystemServerConfiguration|CentralSystemConfiguration|CentralSystemRestServiceConfiguration|CentralSystemFrontEndConfiguration|WSDLEndpointConfiguration|JsonEndpointConfiguration|OCPIEndpointConfiguration|OCPIServiceConfiguration|ODataServiceConfiguration|FirebaseConfiguration|EmailConfiguration|StorageConfiguration|NotificationConfiguration|AuthorizationConfiguration|ChargingStationConfiguration|SchedulerConfiguration|LocalesConfiguration|LoggingConfiguration|HealthCheckConfiguration|MigrationConfiguration|EVDatabaseConfiguration|ChargingStationTemplatesConfiguration|AxiosConfiguration; +export type ConfigurationSection = CryptoConfiguration|CentralSystemServerConfiguration|CentralSystemConfiguration|CentralSystemRestServiceConfiguration|CentralSystemFrontEndConfiguration|WSDLEndpointConfiguration|JsonEndpointConfiguration|OCPIEndpointConfiguration|OCPIServiceConfiguration|ODataServiceConfiguration|FirebaseConfiguration|EmailConfiguration|StorageConfiguration|NotificationConfiguration|AuthorizationConfiguration|ChargingStationConfiguration|SchedulerConfiguration|LocalesConfiguration|LogConfiguration|HealthCheckConfiguration|MigrationConfiguration|EVDatabaseConfiguration|ChargingStationTemplatesConfiguration|AxiosConfiguration; diff --git a/src/types/configuration/FirebaseConfiguration.ts b/src/types/configuration/FirebaseConfiguration.ts index a8e48a2454..e6e974b93d 100644 --- a/src/types/configuration/FirebaseConfiguration.ts +++ b/src/types/configuration/FirebaseConfiguration.ts @@ -11,6 +11,5 @@ export default interface FirebaseConfiguration { tokenURI: string; authProviderX509CertURL: string; clientX509CertURL: string; - databaseURL: string; tenants: TenantConfiguration[]; } diff --git a/src/types/configuration/LogConfiguration.ts b/src/types/configuration/LogConfiguration.ts new file mode 100644 index 0000000000..941e5d5b48 --- /dev/null +++ b/src/types/configuration/LogConfiguration.ts @@ -0,0 +1,3 @@ +export default interface LogConfiguration { + logLevel: string; +} diff --git a/src/types/configuration/LoggingConfiguration.ts b/src/types/configuration/LoggingConfiguration.ts deleted file mode 100644 index 309e913617..0000000000 --- a/src/types/configuration/LoggingConfiguration.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default interface LoggingConfiguration { - logLevel: string; -} diff --git a/src/types/requests/HttpLoggingRequest.ts b/src/types/requests/HttpLogRequest.ts similarity index 100% rename from src/types/requests/HttpLoggingRequest.ts rename to src/types/requests/HttpLogRequest.ts diff --git a/src/utils/Configuration.ts b/src/utils/Configuration.ts index 6ab61350e0..aa9410d7dc 100644 --- a/src/utils/Configuration.ts +++ b/src/utils/Configuration.ts @@ -14,7 +14,7 @@ import EVDatabaseConfiguration from '../types/configuration/EVDatabaseConfigurat import EmailConfiguration from '../types/configuration/EmailConfiguration'; import FirebaseConfiguration from '../types/configuration/FirebaseConfiguration'; import JsonEndpointConfiguration from '../types/configuration/JsonEndpointConfiguration'; -import LoggingConfiguration from '../types/configuration/LoggingConfiguration'; +import LogConfiguration from '../types/configuration/LogConfiguration'; import MigrationConfiguration from '../types/configuration/MigrationConfiguration'; import MonitoringConfiguration from '../types/configuration/MonitoringConfiguration'; import NotificationConfiguration from '../types/configuration/NotificationConfiguration'; @@ -223,10 +223,10 @@ export default class Configuration { return chargingStationConfiguration; } - public static getLoggingConfig(): LoggingConfiguration { - const logging = Configuration.getConfig().Logging; - if (!Configuration.isUndefined('Logging', logging)) { - return logging; + public static getLogConfig(): LogConfiguration { + const log = Configuration.getConfig().Logging; + if (!Configuration.isUndefined('Logging', log)) { + return log; } } diff --git a/src/utils/Logging.ts b/src/utils/Logging.ts index 0f0f4ca635..cb75897d04 100644 --- a/src/utils/Logging.ts +++ b/src/utils/Logging.ts @@ -10,8 +10,8 @@ import BackendError from '../exception/BackendError'; import Configuration from '../utils/Configuration'; import Constants from './Constants'; import { HTTPError } from '../types/HTTPError'; -import LoggingConfiguration from '../types/configuration/LoggingConfiguration'; -import LoggingStorage from '../storage/mongodb/LoggingStorage'; +import LogConfiguration from '../types/configuration/LogConfiguration'; +import LogStorage from '../storage/mongodb/LogStorage'; import { OCPIResult } from '../types/ocpi/OCPIResult'; import { OCPPStatus } from '../types/ocpp/OCPPClient'; import { OICPResult } from '../types/oicp/OICPResult'; @@ -28,14 +28,14 @@ import sizeof from 'object-sizeof'; const MODULE_NAME = 'Logging'; export default class Logging { - private static loggingConfig: LoggingConfiguration; + private static logConfig: LogConfiguration; private static traceConfig: TraceConfiguration; - public static getConfiguration(): LoggingConfiguration { - if (!this.loggingConfig) { - this.loggingConfig = Configuration.getLoggingConfig(); + public static getConfiguration(): LogConfiguration { + if (!this.logConfig) { + this.logConfig = Configuration.getLogConfig(); } - return this.loggingConfig; + return this.logConfig; } public static getTraceConfiguration(): TraceConfiguration { @@ -720,7 +720,7 @@ export default class Logging { public static async traceOcppMessageResponse(module: string, tenant: Tenant, chargingStationID: string, action: ServerAction, request: any, response: any, direction: '<<' | '>>', chargingStationDetails: { siteID: string, siteAreaID: string, companyID: string,}, performanceTracingData?: PerformanceTracingData): Promise { - if (Logging.getTraceConfiguration().traceOcpp) { + if (Logging.getTraceConfiguration().traceOcpp && performanceTracingData) { // Compute duration if provided const executionDurationMillis = performanceTracingData?.startTimestamp ? Date.now() - performanceTracingData.startTimestamp : 0; const sizeOfResponseDataKB = Utils.truncTo(Utils.createDecimal( @@ -880,12 +880,12 @@ export default class Logging { private static async log(log: Log): Promise { // Check Log Level - const loggingConfig = Logging.getConfiguration(); + const logConfig = Logging.getConfiguration(); // Default Log Level - const logLevel = loggingConfig.logLevel ? loggingConfig.logLevel : LogLevel.DEBUG; + const logLevel = logConfig.logLevel ? logConfig.logLevel : LogLevel.DEBUG; // Log Level switch (LogLevel[logLevel]) { - // No logging at all + // No log at all case LogLevel.NONE: return; // Keep all log messages just filter out DEBUG @@ -936,7 +936,7 @@ export default class Logging { log.tenantID = Constants.DEFAULT_TENANT_ID; } // Save - return LoggingStorage.saveLog(log.tenantID, log); + return LogStorage.saveLog(log.tenantID, log); } private static async anonymizeSensitiveData(message: any): Promise { @@ -1007,7 +1007,7 @@ export default class Logging { tenantID: Constants.DEFAULT_TENANT_ID, module: MODULE_NAME, method: 'anonymizeSensitiveData', - action: ServerAction.LOGGING, + action: ServerAction.LOG, message: 'No matching object type for log message anonymisation', detailedMessages: { message } }); diff --git a/src/utils/NotificationHelper.ts b/src/utils/NotificationHelper.ts index 5428136365..d4531c1eed 100644 --- a/src/utils/NotificationHelper.ts +++ b/src/utils/NotificationHelper.ts @@ -6,11 +6,12 @@ import Tenant from '../types/Tenant'; import Transaction from '../types/Transaction'; import User from '../types/User'; import Utils from './Utils'; +import moment from 'moment'; export default class NotificationHelper { public static notifyStartTransaction(tenant: Tenant, transaction: Transaction, chargingStation: ChargingStation, user: User) { if (user) { - void NotificationHandler.sendSessionStarted( + void NotificationHandler.sendTransactionStarted( tenant, transaction.id.toString(), user, @@ -91,7 +92,7 @@ export default class NotificationHelper { // Get the i18n lib const i18nManager = I18nManager.getInstanceForLocale(user.locale); // Send Notification (Async) - void NotificationHandler.sendEndOfSession( + void NotificationHandler.sendEndOfTransaction( tenant, transaction.id.toString() + '-EOS', user, @@ -107,7 +108,7 @@ export default class NotificationHelper { connectorId: Utils.getConnectorLetterFromConnectorID(transaction.connectorId), totalConsumption: i18nManager.formatNumber(Math.round(transaction.stop.totalConsumptionWh / 10) / 100), totalDuration: Utils.transactionDurationToString(transaction), - totalInactivity: Utils.transactionInactivityToString(transaction, user), + totalInactivity: NotificationHelper.transactionInactivityToString(transaction, user), stateOfCharge: transaction.stop.stateOfCharge, evseDashboardChargingStationURL: Utils.buildEvseTransactionURL(tenant.subdomain, transaction.id, '#history'), evseDashboardURL: Utils.buildEvseURL(tenant.subdomain) @@ -116,7 +117,7 @@ export default class NotificationHelper { // Notify Signed Data if (transaction.stop.signedData !== '') { // Send Notification (Async) - void NotificationHandler.sendEndOfSignedSession( + void NotificationHandler.sendEndOfSignedTransaction( tenant, transaction.id.toString() + '-EOSS', user, @@ -149,4 +150,17 @@ export default class NotificationHelper { } } } + + private static transactionInactivityToString(transaction: Transaction, user: User, i18nHourShort = 'h') { + const i18nManager = I18nManager.getInstanceForLocale(user ? user.locale : Constants.DEFAULT_LANGUAGE); + // Get total + const totalInactivitySecs = transaction.stop.totalInactivitySecs; + // None? + if (totalInactivitySecs === 0) { + return `0${i18nHourShort}00 (${i18nManager.formatPercentage(0)})`; + } + // Build the inactivity percentage + const totalInactivityPercent = i18nManager.formatPercentage(Math.round((totalInactivitySecs / transaction.stop.totalDurationSecs) * 100) / 100); + return moment.duration(totalInactivitySecs, 's').format(`h[${i18nHourShort}]mm`, { trim: false }) + ` (${totalInactivityPercent})`; + } } diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index d9781266ae..da7f9233a2 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -16,7 +16,6 @@ import Configuration from './Configuration'; import ConnectorStats from '../types/ConnectorStats'; import Constants from './Constants'; import { Decimal } from 'decimal.js'; -import I18nManager from './I18nManager'; import { Promise } from 'bluebird'; import QRCode from 'qrcode'; import { Request } from 'express'; @@ -1512,10 +1511,12 @@ export default class Utils { } // OCPI if (url.includes('ocpi/cpo')) { - return ServerAction.OCPI_CPO_REQUEST; + // The CPO is called by the EMSP + return ServerAction.OCPI_EMSP_REQUEST; } if (url.includes('ocpi/emsp')) { - return ServerAction.OCPI_EMSP_REQUEST; + // The eMSP is called by the CPO + return ServerAction.OCPI_CPO_REQUEST; } // Hubject if (url.includes('hubject')) { @@ -1679,17 +1680,4 @@ export default class Utils { } return moment.duration(totalDurationSecs, 's').format('h[h]mm', { trim: false }); } - - public static transactionInactivityToString(transaction: Transaction, user: User, i18nHourShort = 'h') { - const i18nManager = I18nManager.getInstanceForLocale(user ? user.locale : Constants.DEFAULT_LANGUAGE); - // Get total - const totalInactivitySecs = transaction.stop.totalInactivitySecs; - // None? - if (totalInactivitySecs === 0) { - return `0${i18nHourShort}00 (${i18nManager.formatPercentage(0)})`; - } - // Build the inactivity percentage - const totalInactivityPercent = i18nManager.formatPercentage(Math.round((totalInactivitySecs / transaction.stop.totalDurationSecs) * 100) / 100); - return moment.duration(totalInactivitySecs, 's').format(`h[${i18nHourShort}]mm`, { trim: false }) + ` (${totalInactivityPercent})`; - } } diff --git a/src/validator/SchemaValidator.ts b/src/validator/SchemaValidator.ts index 0c53096cbb..0eefd418d0 100644 --- a/src/validator/SchemaValidator.ts +++ b/src/validator/SchemaValidator.ts @@ -78,7 +78,7 @@ export default class SchemaValidator { SchemaValidator.settingSchema, SchemaValidator.registrationTokenSchema, SchemaValidator.siteAreasSchema, - SchemaValidator.siteSchema + SchemaValidator.siteSchema, ]); } diff --git a/test/api/BillingTestHelper.ts b/test/api/BillingTestHelper.ts index 63414cc448..fa957ba682 100644 --- a/test/api/BillingTestHelper.ts +++ b/test/api/BillingTestHelper.ts @@ -17,7 +17,7 @@ import ContextProvider from './context/ContextProvider'; import Cypher from '../../src/utils/Cypher'; import { DataResult } from '../../src/types/DataResult'; import Decimal from 'decimal.js'; -import LoggingStorage from '../../src/storage/mongodb/LoggingStorage'; +import LogStorage from '../../src/storage/mongodb/LogStorage'; import SiteAreaContext from './context/SiteAreaContext'; import SiteContext from './context/SiteContext'; import { StatusCodes } from 'http-status-codes'; @@ -526,7 +526,7 @@ export default class BillingTestHelper { public async dumpLastErrors(): Promise { const params = { levels: ['E'] }; const dbParams = { limit: 2, skip: 0, sort: { timestamp: -1 } }; // the 2 last errors - const loggedErrors = await LoggingStorage.getLogs(this.tenantContext.getTenant(), params, dbParams, null); + const loggedErrors = await LogStorage.getLogs(this.tenantContext.getTenant(), params, dbParams, null); if (loggedErrors?.result.length > 0) { for (const loggedError of loggedErrors.result) { console.error( diff --git a/test/api/RegistrationTokenTest.ts b/test/api/RegistrationTokenTest.ts index e3f433fdf7..e873e26c29 100644 --- a/test/api/RegistrationTokenTest.ts +++ b/test/api/RegistrationTokenTest.ts @@ -190,7 +190,7 @@ describe('Registration Token', () => { testData.createdRegistrationTokens[1], false ); - expect(response.status).to.equal(StatusCodes.FORBIDDEN); + expect(response.status).to.equal(StatusCodes.OK); }); // Update diff --git a/test/api/SiteAreaOrgTest.ts b/test/api/SiteAreaOrgTest.ts index e52e7d46fc..78d9e358e8 100644 --- a/test/api/SiteAreaOrgTest.ts +++ b/test/api/SiteAreaOrgTest.ts @@ -1,11 +1,12 @@ -import { HTTPAuthError, HTTPError } from '../../src/types/HTTPError'; import chai, { expect } from 'chai'; import Asset from '../../src/types/Asset'; import CentralServerService from '../api/client/CentralServerService'; +import Constants from '../../src/utils/Constants'; import ContextDefinition from './context/ContextDefinition'; import ContextProvider from './context/ContextProvider'; import Factory from '../factories/Factory'; +import { HTTPError } from '../../src/types/HTTPError'; import Site from '../../src/types/Site'; import SiteArea from '../../src/types/SiteArea'; import SiteAreaContext from './context/SiteAreaContext'; @@ -54,6 +55,25 @@ function login(userRole) { } } +async function createSiteArea() { + // Create the site area + testData.newSiteArea = await testData.userService.createEntity( + testData.userService.siteAreaApi, + Factory.siteArea.build({ siteID: testData.siteContext.getSite().id }) + ); +} + +async function createAsset() { + // Create Asset + testData.testAsset = await testData.userService.createEntity( + testData.userService.assetApi, + Factory.asset.build({ + siteAreaID: testData.newSiteArea.id, + assetType: 'PR' + }) + ); +} + /** * */ @@ -74,7 +94,7 @@ async function createSiteWithSiteAdmin() { // Create a site testData.siteWithSiteAdmin = await testData.userService.createEntity( testData.userService.siteApi, - Factory.site.build({ companyID: testData.tenantContext.getContext().companies[0].id }) + Factory.site.build({ companyID: testData.tenantContext.getContext().companies[1].id }) ); await assignSiteAdmin(ContextDefinition.USER_CONTEXTS.BASIC_USER, testData.siteWithSiteAdmin); testData.createdSites.push(testData.siteWithSiteAdmin); @@ -144,6 +164,18 @@ describe('Site Area', () => { false ); } + // Delete Asset + await testData.centralUserService.deleteEntity( + testData.centralUserService.assetApi, + testData.testAsset, + false + ); + // Delete site area + await testData.centralUserService.deleteEntity( + testData.centralUserService.siteAreaApi, + testData.newSiteArea, + false + ); testData.createdUsers = []; }); @@ -151,18 +183,11 @@ describe('Site Area', () => { beforeAll(async () => { login(ContextDefinition.USER_CONTEXTS.DEFAULT_ADMIN); - // Create the entity - testData.newSiteArea = await testData.userService.createEntity( - testData.userService.siteAreaApi, - Factory.siteArea.build({ siteID: testData.siteContext.getSite().id }) - ); - testData.testAsset = await testData.userService.createEntity( - testData.userService.assetApi, - Factory.asset.build({ - siteAreaID: testData.newSiteArea.id, - assetType: 'PR' - }) - ); + await createSiteArea(); + await createAsset(); + + await createSiteWithSiteAdmin(); + await createSiteWithoutSiteAdmin(); }); it('Should be able to create a new site area', async () => { @@ -270,24 +295,123 @@ describe('Site Area', () => { const response = await testData.userService.siteAreaApi.assignChargingStations( testData.siteAreaContext.getSiteArea().id, [chargingStations.data.result[0].id]); expect(response.status).to.equal(StatusCodes.OK); + // Get the assigned charging station + const chargingStation = (await testData.userService.chargingStationApi.readById(chargingStations.data.result[0].id)).data; + // Get the site + const site = (await testData.userService.siteApi.readById(chargingStation.siteID)).data; + expect(chargingStation.siteAreaID).to.equal(testData.siteAreaContext.getSiteArea().id); + expect(chargingStation.siteID).to.equal(testData.siteAreaContext.getSiteArea().siteID); + expect(chargingStation.companyID).to.equal(site.companyID); }); it('Should be able to remove ChargingStations from SiteArea', async () => { - // Remove ChargingStation from SiteArea + // Remove ChargingStation from SiteArea const chargingStations = await testData.userService.chargingStationApi.readAll({}); expect(chargingStations.status).to.equal(StatusCodes.OK); const response = await testData.userService.siteAreaApi.removeChargingStations( testData.siteAreaContext.getSiteArea().id, [chargingStations.data.result[0].id]); expect(response.status).to.equal(StatusCodes.OK); + // Get the assigned charging station + const chargingStation = (await testData.userService.chargingStationApi.readById(chargingStations.data.result[0].id)).data; + // Organizations entities IDs should be removed + expect(chargingStation.siteAreaID).to.be.null; + expect(chargingStation.siteID).to.be.null; + expect(chargingStation.companyID).to.be.null; + }); + + it('Assets, Charging stations, Transactions and Consumption should be aligned with organizations entities', async () => { + const chargingStations = await testData.userService.chargingStationApi.readAll({}); + let transaction = (await testData.userService.transactionApi.readAllCompleted({}, { limit: 1, skip: 0 })).data.result[0]; + let chargingStation = (await testData.userService.chargingStationApi.readById(chargingStations.data.result[0].id)).data; + // Conserve site areas IDs to re init the context + const oldChargingStationSiteAreaID = chargingStation.siteAreaID; + const oldTransactionSiteAreaID = transaction.siteAreaID; + const oldTransactionSiteID = transaction.siteID; + const transactionSiteArea = (await testData.userService.siteAreaApi.readById(oldTransactionSiteAreaID)).data; + transactionSiteArea.siteID = testData.createdSites[1].id; + // Update + await testData.userService.updateEntity( + testData.userService.siteAreaApi, + transactionSiteArea + ); + transaction = (await testData.userService.transactionApi.readById(transaction.id)).data; + const consumption = (await testData.userService.transactionApi.readAllConsumption({ TransactionId: transaction.id })).data; + expect(transaction.siteID).to.equal(testData.createdSites[1].id); + expect(consumption.siteID).to.equal(testData.createdSites[1].id); + expect(transaction.companyID).to.equal(testData.createdSites[1].companyID); + transactionSiteArea.siteID = oldTransactionSiteID; + // Update + await testData.userService.updateEntity( + testData.userService.siteAreaApi, + transactionSiteArea + ); + // Create the entity + testData.newSiteArea = await testData.userService.createEntity( + testData.userService.siteAreaApi, + Factory.siteArea.build({ siteID: testData.createdSites[0].id }) + ); + let response = await testData.userService.siteAreaApi.assignChargingStations( + testData.newSiteArea.id, [chargingStations.data.result[0].id]); + expect(response.status).to.equal(StatusCodes.OK); + response = await testData.userService.siteAreaApi.assignAssets( + testData.newSiteArea.id, [testData.testAsset.id]); + expect(response.status).to.equal(StatusCodes.OK); + // Get the assigned asset + let asset = (await testData.userService.assetApi.readById(testData.testAsset.id)).data; + expect(asset.siteAreaID).to.equal(testData.newSiteArea.id); + expect(asset.siteID).to.equal(testData.createdSites[0].id); + expect(asset.companyID).to.equal(testData.createdSites[0].companyID); + // Get the assigned charging station + chargingStation = (await testData.userService.chargingStationApi.readById(chargingStations.data.result[0].id)).data; + expect(chargingStation.siteAreaID).to.equal(testData.newSiteArea.id); + expect(chargingStation.siteID).to.equal(testData.createdSites[0].id); + expect(chargingStation.companyID).to.equal(testData.createdSites[0].companyID); + // Change site + testData.newSiteArea.siteID = testData.createdSites[1].id; + // Update + await testData.userService.updateEntity( + testData.userService.siteAreaApi, + testData.newSiteArea + ); + // Get the assigned asset + asset = (await testData.userService.assetApi.readById(testData.testAsset.id)).data; + expect(asset.siteAreaID).to.equal(testData.newSiteArea.id); + expect(asset.siteID).to.equal(testData.createdSites[1].id); + expect(asset.companyID).to.equal(testData.createdSites[1].companyID); + // Get the assigned charging station + chargingStation = (await testData.userService.chargingStationApi.readById(chargingStations.data.result[0].id)).data; + expect(chargingStation.siteAreaID).to.equal(testData.newSiteArea.id); + expect(chargingStation.siteID).to.equal(testData.createdSites[1].id); + expect(chargingStation.companyID).to.equal(testData.createdSites[1].companyID); + // Remove charging station from site area + await testData.userService.siteAreaApi.removeChargingStations( + testData.newSiteArea.id, [chargingStation.id]); + chargingStation = (await testData.userService.chargingStationApi.readById(chargingStation.id)).data; + expect(chargingStation.siteAreaID).to.be.null; + expect(chargingStation.siteID).to.be.null; + expect(chargingStation.companyID).to.be.null; + // Put back the context in place + if (oldChargingStationSiteAreaID) { + await testData.userService.siteAreaApi.assignChargingStations( + oldChargingStationSiteAreaID, [chargingStation.id]); + } + testData.siteAreaContext.setSiteArea((await testData.userService.siteAreaApi.readById(testData.siteAreaContext.getSiteArea().id)).data); }); it('Should be able to assign Assets to SiteArea', async () => { - // Assign Assets to SiteArea + // Assign Assets to SiteArea const assets = await testData.userService.assetApi.readAll({}); expect(assets.status).to.equal(StatusCodes.OK); const response = await testData.userService.siteAreaApi.assignAssets( testData.siteAreaContext.getSiteArea().id, [assets.data.result[0].id]); expect(response.status).to.equal(StatusCodes.OK); + // Get the assigned asset + const asset = (await testData.userService.assetApi.readById(assets.data.result[0].id)).data; + // Get the site + const site = (await testData.userService.siteApi.readById(asset.siteID)).data; + expect(asset.siteAreaID).to.equal(testData.siteAreaContext.getSiteArea().id); + expect(asset.siteID).to.equal(testData.siteAreaContext.getSiteArea().siteID); + expect(asset.companyID).to.equal(site.companyID); }); it('Should be able to remove Assets from SiteArea', async () => { @@ -297,6 +421,11 @@ describe('Site Area', () => { const response = await testData.userService.siteAreaApi.removeAssets( testData.siteAreaContext.getSiteArea().id, [assets.data.result[0].id]); expect(response.status).to.equal(StatusCodes.OK); + const asset = (await testData.userService.assetApi.readById(assets.data.result[0].id)).data; + // Organization IDs should be removed + expect(asset.siteAreaID).to.be.null; + expect(asset.siteID).to.be.null; + expect(asset.companyID).to.be.null; }); }); diff --git a/test/api/SiteOrgTest.ts b/test/api/SiteOrgTest.ts index 7997a97419..e06b75a3f5 100644 --- a/test/api/SiteOrgTest.ts +++ b/test/api/SiteOrgTest.ts @@ -20,6 +20,8 @@ class TestData { public siteContext: SiteContext; public siteAreaContext: any; public newSite: any; + public newSiteArea: any; + public testAsset: any; public newUser: any; public createdSites: any[] = []; public createdUsers: any[] = []; @@ -49,6 +51,25 @@ async function createSite() { testData.createdSites.push(testData.newSite); } +async function createSiteArea() { + // Create the site area + testData.newSiteArea = await testData.userService.createEntity( + testData.userService.siteAreaApi, + Factory.siteArea.build({ siteID: testData.createdSites[0].id }) + ); +} + +async function createAsset() { + // Create Asset + testData.testAsset = await testData.userService.createEntity( + testData.userService.assetApi, + Factory.asset.build({ + siteAreaID: testData.newSiteArea.id, + assetType: 'PR' + }) + ); +} + async function assignUserToSite(userRole, site): Promise { // Assign the user to the site const userContext = await testData.tenantContext.getUserContext(userRole); @@ -99,7 +120,7 @@ describe('Site', () => { describe('With component Organization (utorg)', () => { beforeAll(async () => { - testData.tenantContext = await ContextProvider.defaultInstance.getTenantContext(ContextDefinition.TENANT_CONTEXTS.TENANT_ORGANIZATION); + testData.tenantContext = await ContextProvider.defaultInstance.getTenantContext(ContextDefinition.TENANT_CONTEXTS.TENANT_WITH_ALL_COMPONENTS); testData.centralUserContext = testData.tenantContext.getUserContext(ContextDefinition.USER_CONTEXTS.DEFAULT_ADMIN); testData.centralUserService = new CentralServerService( testData.tenantContext.getTenant().subdomain, @@ -111,6 +132,9 @@ describe('Site', () => { beforeAll(async () => { login(ContextDefinition.USER_CONTEXTS.DEFAULT_ADMIN); + await createSite(); + await createSiteArea(); + await createAsset(); }); afterAll(async () => { @@ -131,6 +155,18 @@ describe('Site', () => { false ); } + // Delete Asset + await testData.centralUserService.deleteEntity( + testData.centralUserService.assetApi, + testData.testAsset, + false + ); + // Delete site area + await testData.centralUserService.deleteEntity( + testData.centralUserService.siteAreaApi, + testData.newSiteArea, + false + ); testData.createdUsers = []; }); @@ -143,6 +179,65 @@ describe('Site', () => { testData.createdSites.push(testData.newSite); }); + it('Assets, Charging stations and transactions should be aligned with organizations entities', async () => { + const chargingStations = await testData.userService.chargingStationApi.readAll({}); + let transaction = (await testData.userService.transactionApi.readAllCompleted({}, { limit: 1, skip: 0 })).data.result[0]; + let chargingStation = (await testData.userService.chargingStationApi.readById(chargingStations.data.result[0].id)).data; + // Conserve site areas ID to re init the context + const oldChargingStationSiteAreaID = chargingStation.siteAreaID; + // Conserve company ID to re init the context + const oldTransactionCompanyID = transaction.companyID; + // Get the site of the transaction + const transactionSite = (await testData.userService.siteApi.readById(transaction.siteID)).data; + // Change the companyID of the Site + transactionSite.companyID = testData.tenantContext.getContext().companies[0].id; + // Update + await testData.userService.updateEntity( + testData.userService.siteApi, + transactionSite + ); + // Get the updated site + transaction = (await testData.userService.transactionApi.readById(transaction.id)).data; + expect(transaction.companyID).to.equal(testData.tenantContext.getContext().companies[0].id); + // Assign Charging Station + await testData.userService.siteAreaApi.assignChargingStations( + testData.newSiteArea.id, [chargingStation.id]); + testData.createdSites[0].companyID = testData.tenantContext.getContext().companies[1].id; + // Update + await testData.userService.updateEntity( + testData.userService.siteApi, + testData.createdSites[0] + ); + // Get the assigned asset + testData.testAsset = (await testData.userService.assetApi.readById(testData.testAsset.id)).data; + expect(testData.testAsset.companyID).to.equal(testData.tenantContext.getContext().companies[1].id); + // Get the assigned charging station + chargingStation = (await testData.userService.chargingStationApi.readById(chargingStations.data.result[0].id)).data; + expect(chargingStation.companyID).to.equal(testData.tenantContext.getContext().companies[1].id); + // Put back the context in place + testData.createdSites[0].companyID = testData.tenantContext.getContext().companies[0].id; + // Update + await testData.userService.updateEntity( + testData.userService.siteApi, + testData.createdSites[0] + ); + transactionSite.companyID = oldTransactionCompanyID; + // Update + await testData.userService.updateEntity( + testData.userService.siteApi, + transactionSite + ); + // Remove charging station from site area + await testData.userService.siteAreaApi.removeChargingStations( + testData.newSiteArea.id, [chargingStation.id]); + chargingStation = (await testData.userService.chargingStationApi.readById(chargingStation.id)).data; + // Put back the context in place + if (oldChargingStationSiteAreaID) { + await testData.userService.siteAreaApi.assignChargingStations( + oldChargingStationSiteAreaID, [chargingStation.id]); + } + }); + it('Should find the created site by id', async () => { // Check if the created entity can be retrieved with its id await testData.userService.getEntityById( @@ -280,7 +375,18 @@ describe('Site', () => { false ); } + // Delete created asset testData.createdUsers = []; + await testData.centralUserService.deleteEntity( + testData.centralUserService.assetApi, + testData.testAsset, + false + ); + await testData.centralUserService.deleteEntity( + testData.centralUserService.siteAreaApi, + testData.newSiteArea, + false + ); }); it('Should find a site he is assigned to', async () => { @@ -313,7 +419,7 @@ describe('Site', () => { 'Should not find a site he is not assigned to in the site list', async () => { try { - // Check if the created entity is in the list + // Check if the created entity is in the list await testData.userService.checkEntityInList( testData.userService.siteApi, testData.createdSites[1] diff --git a/test/api/SmartChargingTest.ts b/test/api/SmartChargingTest.ts index 2cc94cfbc0..efa17da4cb 100644 --- a/test/api/SmartChargingTest.ts +++ b/test/api/SmartChargingTest.ts @@ -14,7 +14,7 @@ import Constants from '../../src/utils/Constants'; import ContextDefinition from './context/ContextDefinition'; import ContextProvider from './context/ContextProvider'; import Cypher from '../../src/utils/Cypher'; -import LoggingStorage from '../../src/storage/mongodb/LoggingStorage'; +import LogStorage from '../../src/storage/mongodb/LogStorage'; import MongoDBStorage from '../../src/storage/mongodb/MongoDBStorage'; import { ServerAction } from '../../src/types/Server'; import SiteAreaContext from './context/SiteAreaContext'; @@ -436,7 +436,7 @@ describeif(testData.chargingSettingProvided)('Smart Charging Service', () => { async () => { await smartChargingIntegration.buildChargingProfiles(testData.siteAreaContext.getSiteArea(), [testData.chargingStationContext1.getChargingStation().id]); // Get the log of the site area limitation adjustment and check the root fuse - const log = await LoggingStorage.getLogs(testData.tenantContext.getTenant(), { actions: [ServerAction.SMART_CHARGING], search: 'currently being used' }, Constants.DB_PARAMS_SINGLE_RECORD, null); + const log = await LogStorage.getLogs(testData.tenantContext.getTenant(), { actions: [ServerAction.SMART_CHARGING], search: 'currently being used' }, Constants.DB_PARAMS_SINGLE_RECORD, null); const siteArea = testData.siteAreaContext.getSiteArea(); const siteAreaLimitPerPhase = Utils.createDecimal(siteArea.maximumPower).div(siteArea.voltage).div(3).toNumber(); const connectorLimit = Utils.createDecimal(Utils.getChargingStationAmperage(testData.chargingStationContext1.getChargingStation(), null, 1)).toNumber(); @@ -700,7 +700,7 @@ describeif(testData.chargingSettingProvided)('Smart Charging Service', () => { } ]); // Check adjustment of site area limit - const log = await LoggingStorage.getLogs(testData.tenantContext.getTenant(), { actions: [ServerAction.SMART_CHARGING], search: 'currently being used' }, Constants.DB_PARAMS_SINGLE_RECORD, null); + const log = await LogStorage.getLogs(testData.tenantContext.getTenant(), { actions: [ServerAction.SMART_CHARGING], search: 'currently being used' }, Constants.DB_PARAMS_SINGLE_RECORD, null); const chargingStation = testData.chargingStationContext1.getChargingStation(); const siteArea = testData.siteAreaContext.getSiteArea(); const siteAreaLimitPerPhase = Utils.createDecimal(siteArea.maximumPower).div(siteArea.voltage).div(3).toNumber(); @@ -716,7 +716,7 @@ describeif(testData.chargingSettingProvided)('Smart Charging Service', () => { async () => { await testData.chargingStationContext.stopTransaction(transaction.id, transaction.tagID, 200, new Date); await smartChargingIntegration.buildChargingProfiles(testData.siteAreaContext.getSiteArea()); - const log = await LoggingStorage.getLogs(testData.tenantContext.getTenant(), { actions: [ServerAction.SMART_CHARGING], search: 'currently being used' }, Constants.DB_PARAMS_SINGLE_RECORD, null); + const log = await LogStorage.getLogs(testData.tenantContext.getTenant(), { actions: [ServerAction.SMART_CHARGING], search: 'currently being used' }, Constants.DB_PARAMS_SINGLE_RECORD, null); const siteArea = testData.siteAreaContext.getSiteArea(); const siteAreaLimitPerPhase = Utils.createDecimal(siteArea.maximumPower).div(siteArea.voltage).div(3).toNumber(); const connectorLimitSinglePhased = Utils.createDecimal( @@ -756,7 +756,7 @@ describeif(testData.chargingSettingProvided)('Smart Charging Service', () => { 'Test if one charging connector is excluded from root fuse when charging station is excluded', async () => { await smartChargingIntegration.buildChargingProfiles(testData.siteAreaContext.getSiteArea(), [testData.chargingStationContext.getChargingStation().id]); - const log = await LoggingStorage.getLogs(testData.tenantContext.getTenant(), { actions: [ServerAction.SMART_CHARGING], search: 'currently being used' }, Constants.DB_PARAMS_SINGLE_RECORD, null); + const log = await LogStorage.getLogs(testData.tenantContext.getTenant(), { actions: [ServerAction.SMART_CHARGING], search: 'currently being used' }, Constants.DB_PARAMS_SINGLE_RECORD, null); const siteArea = testData.siteAreaContext.getSiteArea(); expect(log.result[0].detailedMessages).include('"fusePhase1": ' + Utils.createDecimal(siteArea.maximumPower).div(siteArea.voltage).minus( @@ -781,7 +781,7 @@ describeif(testData.chargingSettingProvided)('Smart Charging Service', () => { 'Test if both charging connectors are excluded from root fuse when charging station is excluded', async () => { await smartChargingIntegration.buildChargingProfiles(testData.siteAreaContext.getSiteArea(), [testData.chargingStationContext.getChargingStation().id]); - const log = await LoggingStorage.getLogs(testData.tenantContext.getTenant(), { actions: [ServerAction.SMART_CHARGING], search: 'currently being used' }, Constants.DB_PARAMS_SINGLE_RECORD, null); + const log = await LogStorage.getLogs(testData.tenantContext.getTenant(), { actions: [ServerAction.SMART_CHARGING], search: 'currently being used' }, Constants.DB_PARAMS_SINGLE_RECORD, null); const siteArea = testData.siteAreaContext.getSiteArea(); expect(log.result[0].detailedMessages).include('"fusePhase1": ' + Utils.createDecimal(siteArea.maximumPower).div(siteArea.voltage).minus( @@ -999,7 +999,7 @@ describeif(testData.chargingSettingProvided)('Smart Charging Service', () => { 'Test if whole charge point is excluded from root fuse when charging station is excluded (one connector charging)', async () => { await smartChargingIntegration.buildChargingProfiles(testData.siteAreaContext.getSiteArea(), [testData.chargingStationContext.getChargingStation().id]); - const log = await LoggingStorage.getLogs(testData.tenantContext.getTenant(), { actions: [ServerAction.SMART_CHARGING], search: 'currently being used' }, Constants.DB_PARAMS_SINGLE_RECORD, null); + const log = await LogStorage.getLogs(testData.tenantContext.getTenant(), { actions: [ServerAction.SMART_CHARGING], search: 'currently being used' }, Constants.DB_PARAMS_SINGLE_RECORD, null); const chargingStation = testData.chargingStationContext.getChargingStation(); const chargePoint = chargingStation.chargePoints.find((cp) => cp.connectorIDs.includes(transaction.connectorId)); const siteArea = testData.siteAreaContext.getSiteArea(); @@ -1055,7 +1055,7 @@ describeif(testData.chargingSettingProvided)('Smart Charging Service', () => { 'Test if only charge point is excluded from root fuse when charging station is excluded (two connectors charging)', async () => { await smartChargingIntegration.buildChargingProfiles(testData.siteAreaContext.getSiteArea(), [testData.chargingStationContext.getChargingStation().id]); - const log = await LoggingStorage.getLogs(testData.tenantContext.getTenant(), { actions: [ServerAction.SMART_CHARGING], search: 'currently being used' }, Constants.DB_PARAMS_SINGLE_RECORD, null); + const log = await LogStorage.getLogs(testData.tenantContext.getTenant(), { actions: [ServerAction.SMART_CHARGING], search: 'currently being used' }, Constants.DB_PARAMS_SINGLE_RECORD, null); const chargingStation = testData.chargingStationContext.getChargingStation(); const chargePoint = chargingStation.chargePoints.find((cp) => cp.connectorIDs.includes(transaction1.connectorId)); const siteArea = testData.siteAreaContext.getSiteArea(); diff --git a/test/api/client/LogsApi.ts b/test/api/client/LogsApi.ts index 6661497502..e4eb1bca90 100644 --- a/test/api/client/LogsApi.ts +++ b/test/api/client/LogsApi.ts @@ -1,3 +1,4 @@ +import { RESTServerRoute } from '../../../src/types/Server'; import CrudApi from './utils/CrudApi'; import TestConstants from './utils/TestConstants'; @@ -7,10 +8,10 @@ export default class LogsApi extends CrudApi { } public async readById(id) { - return super.readById(id, '/client/api/Logging'); + return super.readById(id, this.buildRestEndpointUrl(RESTServerRoute.REST_LOG, { id })); } public async readAll(params, paging = TestConstants.DEFAULT_PAGING, ordering = TestConstants.DEFAULT_ORDERING) { - return super.readAll(params, paging, ordering, '/client/api/Loggings'); + return super.readAll(params, paging, ordering, this.buildRestEndpointUrl(RESTServerRoute.REST_LOGS)); } } diff --git a/test/api/client/SiteAreaApi.ts b/test/api/client/SiteAreaApi.ts index 8f52bb69d6..4a81409379 100644 --- a/test/api/client/SiteAreaApi.ts +++ b/test/api/client/SiteAreaApi.ts @@ -56,7 +56,7 @@ export default class SiteAreaApi extends CrudApi { return super.update({ assetIDs }, this.buildRestEndpointUrl(RESTServerRoute.REST_SITE_AREA_ASSIGN_ASSETS, { id: siteAreaID })); } - public async removeAssets(siteAreaID: string, assetIDs) { + public async removeAssets(siteAreaID: string, assetIDs: string[]) { return super.update({ assetIDs }, this.buildRestEndpointUrl(RESTServerRoute.REST_SITE_AREA_REMOVE_ASSETS, { id: siteAreaID })); } } diff --git a/test/api/client/TransactionApi.ts b/test/api/client/TransactionApi.ts index 73ee9a7b12..2e197f38f0 100644 --- a/test/api/client/TransactionApi.ts +++ b/test/api/client/TransactionApi.ts @@ -24,7 +24,8 @@ export default class TransactionApi extends CrudApi { } public async readAllConsumption(params) { - return super.read(params, `${this.buildRestEndpointUrl(RESTServerRoute.REST_TRANSACTION_CONSUMPTIONS, { id: params.TransactionId })}?WithUser=true`); + const id = params.TransactionId; + return super.read(params, `${this.buildRestEndpointUrl(RESTServerRoute.REST_TRANSACTION_CONSUMPTIONS, { id })}?WithUser=true&LoadAllConsumptions=true`); } public async readAllYears(params) { diff --git a/test/api/context/ContextDefinition.ts b/test/api/context/ContextDefinition.ts index d236bdae19..05d13bfe33 100644 --- a/test/api/context/ContextDefinition.ts +++ b/test/api/context/ContextDefinition.ts @@ -585,6 +585,9 @@ export default class ContextDefinition { static readonly TENANT_COMPANY_LIST: any[] = [ { // Default company no settings yet id: '5ce249a2372f0b1c8caf928f' + }, + { // Second company no settings yet + id: '5ce249a2372f0b1c8caf928e' } ]; @@ -624,42 +627,48 @@ export default class ContextDefinition { name: `${ContextDefinition.SITE_CONTEXTS.SITE_BASIC}-${ContextDefinition.SITE_AREA_CONTEXTS.WITH_ACL}`, numberOfPhases: 3, accessControl: true, - siteName: ContextDefinition.SITE_CONTEXTS.SITE_BASIC + siteName: ContextDefinition.SITE_CONTEXTS.SITE_BASIC, + voltage: Voltage.VOLTAGE_230 }, { // Without access control id: '5ce249a2372f0b1c8caf5476', name: `${ContextDefinition.SITE_CONTEXTS.SITE_BASIC}-${ContextDefinition.SITE_AREA_CONTEXTS.WITHOUT_ACL}`, numberOfPhases: 3, accessControl: false, - siteName: ContextDefinition.SITE_CONTEXTS.SITE_BASIC + siteName: ContextDefinition.SITE_CONTEXTS.SITE_BASIC, + voltage: Voltage.VOLTAGE_230 }, { // With access control id: '5ce249a2372f0b1c8caf1234', name: `${ContextDefinition.SITE_CONTEXTS.SITE_WITH_AUTO_USER_ASSIGNMENT}-${ContextDefinition.SITE_AREA_CONTEXTS.WITH_ACL}`, numberOfPhases: 3, accessControl: true, - siteName: ContextDefinition.SITE_CONTEXTS.SITE_WITH_AUTO_USER_ASSIGNMENT + siteName: ContextDefinition.SITE_CONTEXTS.SITE_WITH_AUTO_USER_ASSIGNMENT, + voltage: Voltage.VOLTAGE_230 }, { // Without access control id: '5ce249a2372f0b1c8caf4678', name: `${ContextDefinition.SITE_CONTEXTS.SITE_WITH_AUTO_USER_ASSIGNMENT}-${ContextDefinition.SITE_AREA_CONTEXTS.WITHOUT_ACL}`, numberOfPhases: 3, accessControl: false, - siteName: ContextDefinition.SITE_CONTEXTS.SITE_WITH_AUTO_USER_ASSIGNMENT + siteName: ContextDefinition.SITE_CONTEXTS.SITE_WITH_AUTO_USER_ASSIGNMENT, + voltage: Voltage.VOLTAGE_230 }, { // With access control id: '5ce249a2372f0b1c8caf5497', name: `${ContextDefinition.SITE_CONTEXTS.SITE_WITH_OTHER_USER_STOP_AUTHORIZATION}-${ContextDefinition.SITE_AREA_CONTEXTS.WITH_ACL}`, numberOfPhases: 3, accessControl: true, - siteName: ContextDefinition.SITE_CONTEXTS.SITE_WITH_OTHER_USER_STOP_AUTHORIZATION + siteName: ContextDefinition.SITE_CONTEXTS.SITE_WITH_OTHER_USER_STOP_AUTHORIZATION, + voltage: Voltage.VOLTAGE_230 }, { // Without access control id: '5ce249a2372f0b1c8caf5432', name: `${ContextDefinition.SITE_CONTEXTS.SITE_WITH_OTHER_USER_STOP_AUTHORIZATION}-${ContextDefinition.SITE_AREA_CONTEXTS.WITHOUT_ACL}`, numberOfPhases: 3, accessControl: false, - siteName: ContextDefinition.SITE_CONTEXTS.SITE_WITH_OTHER_USER_STOP_AUTHORIZATION + siteName: ContextDefinition.SITE_CONTEXTS.SITE_WITH_OTHER_USER_STOP_AUTHORIZATION, + voltage: Voltage.VOLTAGE_230 }, // Smart Charging must be deactivated. (Connection to CS will fail, because they do not exist) { // With smart charging three phased