Migrated EMSP Tokens endpoint
MODIFY
src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/EMSPService.ts
src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/EMSPService.ts
@@ -3,7 +3,6 @@ import EMSPCdrsEndpoint from './emsp/EMSPCdrsEndpoint';
import EMSPCommandsEndpoint from './emsp/EMSPCommandsEndpoint';
import EMSPSessionsEndpoint from './emsp/EMSPSessionsEndpoint';
import EMSPTariffsEndpoint from './emsp/EMSPTariffsEndpoint';
-import EMSPTokensEndpoint from './emsp/EMSPTokensEndpoint';
import OCPIServiceConfiguration from '../../../../types/configuration/OCPIServiceConfiguration';
export default class EMSPService extends AbstractOCPIService {
@@ -12,7 +11,6 @@ export default class EMSPService extends AbstractOCPIService {
public constructor(ocpiRestConfig: OCPIServiceConfiguration) {
super(ocpiRestConfig, EMSPService.PATH, EMSPService.VERSION);
- this.registerEndpoint(new EMSPTokensEndpoint(this));
this.registerEndpoint(new EMSPSessionsEndpoint(this));
this.registerEndpoint(new EMSPCdrsEndpoint(this));
this.registerEndpoint(new EMSPCommandsEndpoint(this));

MODIFY
src/server/ocpi/router/emsp/EMSPRouter.ts
src/server/ocpi/router/emsp/EMSPRouter.ts
@@ -4,6 +4,7 @@ import express, { NextFunction, Request, Response } from 'express';
import CPOEMSPCredentialsRouterV211 from '../common/V2.1.1/CPOEMSPCredentialsRouterV211';
import EMSPLocationsRouterV211 from './V2.1.1/EMSPLocationsRouterV211';
+import EMSPTokensRouterV211 from './V2.1.1/EMSPTokensRouterV211';
import EMSPVersionsService from '../../service/emsp/EMSPVersionsService';
import RouterUtils from '../../../../utils/RouterUtils';
@@ -28,6 +29,7 @@ export default class EMSPRouter {
protected buildRouteEmspV211(): void {
this.router.use('/2.1.1', [
+ new EMSPTokensRouterV211().buildRoutes(),
new EMSPLocationsRouterV211().buildRoutes(),
new CPOEMSPCredentialsRouterV211().buildRoutes(),
]);

MODIFY
src/server/ocpi/router/emsp/V2.1.1/EMSPLocationsRouterV211.ts
src/server/ocpi/router/emsp/V2.1.1/EMSPLocationsRouterV211.ts
-import { OCPIServerRoute, ServerAction } from '../../../../../types/Server';
/* eslint-disable @typescript-eslint/no-misused-promises */
+import { OCPIServerRoute, ServerAction } from '../../../../../types/Server';
import express, { NextFunction, Request, Response } from 'express';
import EMSPLocationsService from '../../../service/emsp/v2.1.1/EMSPLocationsService';

ADD
src/server/ocpi/router/emsp/V2.1.1/EMSPTokensRouterV211.ts
+/* eslint-disable @typescript-eslint/no-misused-promises */
+import { OCPIServerRoute, ServerAction } from '../../../../../types/Server';
+import express, { NextFunction, Request, Response } from 'express';
+
+import EMSPTokensService from '../../../service/emsp/v2.1.1/EMSPTokensService';
+import RouterUtils from '../../../../../utils/RouterUtils';
+
+export default class EMSPTokensRouterV211 {
+ private router: express.Router;
+
+ public constructor() {
+ this.router = express.Router();
+ }
+
+ public buildRoutes(): express.Router {
+ this.buildRouteAuthorizeToken();
+ this.buildRouteGetTokens();
+ return this.router;
+ }
+
+ protected buildRouteAuthorizeToken(): void {
+ this.router.post(`/${OCPIServerRoute.OCPI_TOKENS}*`, async (req: Request, res: Response, next: NextFunction) => {
+ await RouterUtils.handleServerAction(EMSPTokensService.handleAuthorizeToken.bind(this), ServerAction.OCPI_EMSP_AUTHORIZE_TOKEN, req, res, next);
+ });
+ }
+
+ protected buildRouteGetTokens(): void {
+ this.router.get(`/${OCPIServerRoute.OCPI_TOKENS}*`, async (req: Request, res: Response, next: NextFunction) => {
+ await RouterUtils.handleServerAction(EMSPTokensService.handleGetTokens.bind(this), ServerAction.OCPI_EMSP_GET_TOKENS, req, res, next);
+ });
+ }
+}

MODIFY
src/server/ocpi/service/OCPIUtilsService.ts
src/server/ocpi/service/OCPIUtilsService.ts
@@ -45,11 +45,9 @@ import moment from 'moment';
const MODULE_NAME = 'OCPIUtilsService';
export default class OCPIUtilsService {
- public static getServiceUrl(req: Request): string {
+ public static getServiceUrl(req: Request, role: string): string {
const baseUrl = OCPIUtilsService.getBaseUrl(req);
- const path = req.path;
- // Return Service url
- return `${baseUrl}${path}`;
+ return `${baseUrl}/ocpi/${role}`;
}
public static getBaseUrl(req: Request): string {

MODIFY
src/server/ocpi/service/common/v2.1.1/CPOEMSPCredentialsService.ts
src/server/ocpi/service/common/v2.1.1/CPOEMSPCredentialsService.ts
@@ -180,7 +180,7 @@ export default class CPOEMSPCredentialsService {
// Save ocpi endpoint
await OCPIEndpointStorage.saveOcpiEndpoint(tenant, ocpiEndpoint);
// Get base url
- const versionUrl = OCPIUtilsService.getServiceUrl(req) + AbstractOCPIService.VERSIONS_PATH;
+ const versionUrl = OCPIUtilsService.getServiceUrl(req, ocpiEndpoint.role.toLocaleLowerCase()) + AbstractOCPIService.VERSIONS_PATH;
// Build credential object
const respCredential = await OCPIUtils.buildOCPICredentialObject(tenant, ocpiEndpoint.localToken, ocpiEndpoint.role, versionUrl);
// Log available OCPI Versions

RENAME
src/server/ocpi/ocpi-services-impl/ocpi-2.1.1/emsp/EMSPTokensEndpoint.ts
src/server/ocpi/service/emsp/v2.1.1/EMSPTokensService.ts
import { NextFunction, Request, Response } from 'express';
-import AbstractEndpoint from '../../AbstractEndpoint';
-import AbstractOCPIService from '../../../AbstractOCPIService';
import AppError from '../../../../../exception/AppError';
import ChargingStationStorage from '../../../../../storage/mongodb/ChargingStationStorage';
import Constants from '../../../../../utils/Constants';
import { HTTPError } from '../../../../../types/HTTPError';
import { OCPIAllowed } from '../../../../../types/ocpi/OCPIAuthorizationInfo';
-import OCPIEndpoint from '../../../../../types/ocpi/OCPIEndpoint';
import { OCPILocationReference } from '../../../../../types/ocpi/OCPILocation';
-import { OCPIResponse } from '../../../../../types/ocpi/OCPIResponse';
import { OCPIStatusCode } from '../../../../../types/ocpi/OCPIStatusCode';
import OCPIUtils from '../../../OCPIUtils';
-import OCPIUtilsService from '../../../service/OCPIUtilsService';
+import OCPIUtilsService from '../../OCPIUtilsService';
import { ServerAction } from '../../../../../types/Server';
import TagStorage from '../../../../../storage/mongodb/TagStorage';
-import Tenant from '../../../../../types/Tenant';
import { UserStatus } from '../../../../../types/User';
import UserStorage from '../../../../../storage/mongodb/UserStorage';
import Utils from '../../../../../utils/Utils';
-const MODULE_NAME = 'EMSPTokensEndpoint';
+const MODULE_NAME = 'EMSPTokensService';
-export default class EMSPTokensEndpoint extends AbstractEndpoint {
- public constructor(ocpiService: AbstractOCPIService) {
- super(ocpiService, 'tokens');
- }
-
- public async process(req: Request, res: Response, next: NextFunction, tenant: Tenant, ocpiEndpoint: OCPIEndpoint): Promise<OCPIResponse> {
- switch (req.method) {
- case 'POST':
- return this.authorizeRequest(req, res, next, tenant);
- case 'GET':
- return this.getTokensRequest(req, res, next, tenant);
- }
- }
-
- private async getTokensRequest(req: Request, res: Response, next: NextFunction, tenant: Tenant): Promise<OCPIResponse> {
+export default class EMSPTokensService {
+ public static async handleGetTokens(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
+ const { tenant } = req;
// Get query parameters
const offset = (req.query.offset) ? Utils.convertToInt(req.query.offset) : 0;
const limit = Utils.convertToInt(req.query.limit) > 0 ? Utils.convertToInt(req.query.limit) : Constants.DB_RECORD_COUNT_NO_LIMIT;
// Get all tokens
- const tokens = await OCPIUtilsService.getEmspTokens(tenant, limit, offset, Utils.convertToDate(req.query.date_from), Utils.convertToDate(req.query.date_to));
+ const tokens = await OCPIUtilsService.getEmspTokens(
+ tenant, limit, offset, Utils.convertToDate(req.query.date_from), Utils.convertToDate(req.query.date_to));
// Set header
res.set({
'X-Total-Count': tokens.count,
'X-Limit': Constants.OCPI_RECORDS_LIMIT
});
// Return next link
- const nextUrl = OCPIUtils.buildNextUrl(req, this.getBaseUrl(req), offset, limit, tokens.count);
+ const nextUrl = OCPIUtils.buildNextUrl(req, OCPIUtilsService.getBaseUrl(req), offset, limit, tokens.count);
if (nextUrl) {
res.links({
next: nextUrl
});
}
- return OCPIUtils.success(tokens.result);
+ res.json(OCPIUtils.success(tokens.result));
+ next();
}
- private async authorizeRequest(req: Request, res: Response, next: NextFunction, tenant: Tenant): Promise<OCPIResponse> {
+ public static async handleAuthorizeToken(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
+ const { tenant } = req;
const urlSegment = req.path.substring(1).split('/');
// Remove action
urlSegment.shift();
@@ -65,8 +51,7 @@ export default class EMSPTokensEndpoint extends AbstractEndpoint {
const tokenID = urlSegment.shift();
if (!tokenID) {
throw new AppError({
- action: ServerAction.OCPI_EMSP_AUTHORIZE_TOKEN,
- module: MODULE_NAME, method: 'authorizeRequest',
+ module: MODULE_NAME, method: 'handleAuthorizeToken', action,
errorCode: HTTPError.GENERAL_ERROR,
message: 'Missing request parameters',
ocpiError: OCPIStatusCode.CODE_2001_INVALID_PARAMETER_ERROR
@@ -75,8 +60,7 @@ export default class EMSPTokensEndpoint extends AbstractEndpoint {
const location = req.body as OCPILocationReference;
if (!location) {
throw new AppError({
- action: ServerAction.OCPI_EMSP_AUTHORIZE_TOKEN,
- module: MODULE_NAME, method: 'authorizeRequest',
+ module: MODULE_NAME, method: 'handleAuthorizeToken', action,
errorCode: HTTPError.GENERAL_ERROR,
ocpiError: OCPIStatusCode.CODE_2002_NOT_ENOUGH_INFORMATION_ERROR,
message: 'Missing Location data',
@@ -85,8 +69,7 @@ export default class EMSPTokensEndpoint extends AbstractEndpoint {
}
if (Utils.isEmptyArray(location.evse_uids)) {
throw new AppError({
- action: ServerAction.OCPI_EMSP_AUTHORIZE_TOKEN,
- module: MODULE_NAME, method: 'authorizeRequest',
+ module: MODULE_NAME, method: 'handleAuthorizeToken', action,
errorCode: HTTPError.GENERAL_ERROR,
ocpiError: OCPIStatusCode.CODE_2002_NOT_ENOUGH_INFORMATION_ERROR,
message: 'Missing Charging Station ID',
@@ -95,8 +78,7 @@ export default class EMSPTokensEndpoint extends AbstractEndpoint {
}
if (location.evse_uids.length > 1) {
throw new AppError({
- action: ServerAction.OCPI_EMSP_AUTHORIZE_TOKEN,
- module: MODULE_NAME, method: 'authorizeRequest',
+ module: MODULE_NAME, method: 'handleAuthorizeToken', action,
errorCode: HTTPError.GENERAL_ERROR,
ocpiError: OCPIStatusCode.CODE_2001_INVALID_PARAMETER_ERROR,
message: 'Does not support authorization on multiple Charging Stations',
@@ -108,8 +90,7 @@ export default class EMSPTokensEndpoint extends AbstractEndpoint {
tenant, location.location_id, location.evse_uids[0]);
if (!chargingStation) {
throw new AppError({
- action: ServerAction.OCPI_EMSP_AUTHORIZE_TOKEN,
- module: MODULE_NAME, method: 'authorizeRequest',
+ module: MODULE_NAME, method: 'handleAuthorizeToken', action,
errorCode: HTTPError.GENERAL_ERROR,
ocpiError: OCPIStatusCode.CODE_2003_UNKNOWN_LOCATION_ERROR,
message: `Charging Station with EVSE ID '${location.evse_uids[0]}' and Location ID '${location.location_id}' does not exist`,
@@ -119,8 +100,7 @@ export default class EMSPTokensEndpoint extends AbstractEndpoint {
const tag = await TagStorage.getTag(tenant, tokenID, { withUser: true });
if (!tag) {
throw new AppError({
- action: ServerAction.OCPI_EMSP_AUTHORIZE_TOKEN,
- module: MODULE_NAME, method: 'authorizeRequest',
+ module: MODULE_NAME, method: 'handleAuthorizeToken', action,
errorCode: HTTPError.GENERAL_ERROR,
ocpiError: OCPIStatusCode.CODE_2001_INVALID_PARAMETER_ERROR,
message: `Unkwnown Tag ID '${tokenID}'`,
@@ -129,17 +109,18 @@ export default class EMSPTokensEndpoint extends AbstractEndpoint {
}
// Check Tag
if (!tag.issuer || !tag.active) {
- return OCPIUtils.success({
+ res.json(OCPIUtils.success({
allowed: OCPIAllowed.NOT_ALLOWED,
authorization_id: Utils.generateUUID(), location
- });
+ }));
+ next();
+ return;
}
// Check User
const user = tag.user;
if (!user) {
throw new AppError({
- action: ServerAction.OCPI_EMSP_AUTHORIZE_TOKEN,
- module: MODULE_NAME, method: 'authorizeRequest',
+ module: MODULE_NAME, method: 'handleAuthorizeToken', action,
errorCode: HTTPError.GENERAL_ERROR,
ocpiError: OCPIStatusCode.CODE_2001_INVALID_PARAMETER_ERROR,
message: `Unkwnown User for OCPI Token ID '${tokenID}'`,
@@ -147,19 +128,22 @@ export default class EMSPTokensEndpoint extends AbstractEndpoint {
});
}
if (user.status !== UserStatus.ACTIVE) {
- return OCPIUtils.success({
+ res.json(OCPIUtils.success({
allowed: tag.user.status === UserStatus.BLOCKED ? OCPIAllowed.BLOCKED : OCPIAllowed.NOT_ALLOWED,
authorization_id: Utils.generateUUID(), location
- });
+ }));
+ next();
+ return;
}
// Generate and Save Auth ID
user.authorizationID = Utils.generateUUID();
await UserStorage.saveUser(tenant, user);
- return OCPIUtils.success({
+ res.json(OCPIUtils.success({
allowed: OCPIAllowed.ALLOWED,
authorization_id: user.authorizationID,
location
- });
+ }));
+ next();
}
}

MODIFY
src/types/Server.ts
src/types/Server.ts
@@ -174,6 +174,7 @@ export enum ServerAction {
OCPI_EMSP_STOP_SESSION = 'OcpiEmspStopSession',
OCPI_EMSP_UPDATE_TOKENS = 'OcpiEmspUpdateTokens',
OCPI_EMSP_GET_CDRS = 'OcpiEmspGetCdrs',
+ OCPI_EMSP_GET_TOKENS = 'OcpiEmspGetTokens',
OCPI_EMSP_CREATE_CDR = 'OcpiEmspCreateCdr',
OCPI_EMSP_RESERVE_NOW = 'OcpiEmspReserveNow',
OCPI_EMSP_UNLOCK_CONNECTOR = 'OcpiEmspUnlockConnector',

Migrated EMSP Tokens endpoint