Added registration tokens JSON schema validation
ADD
src/assets/schemas/registration-token/registration-token.json
+{
+ "$id": "registration-token",
+ "definitions": {
+ "id": {
+ "$ref": "common#/definitions/id"
+ },
+ "description": {
+ "type": "string",
+ "sanitize": "mongo"
+ },
+ "siteAreaID": {
+ "$ref": "common#/definitions/id"
+ },
+ "expirationDate": {
+ "type": "string",
+ "format": "date-time",
+ "sanitize": "mongo"
+ }
+ }
+}

ADD
src/assets/server/rest/v1/schemas/registration-token/registration-token-by-id.json
+{
+ "$id": "registration-token-by-id",
+ "title": "Registration Token by id Request",
+ "description": "",
+ "type": "object",
+ "properties": {
+ "ID": {
+ "$ref": "registration-token#/definitions/id"
+ }
+ },
+ "required": [
+ "ID"
+ ]
+}

ADD
src/assets/server/rest/v1/schemas/registration-token/registration-token-create.json
+{
+ "$id": "registration-token-create",
+ "title": "Registration Token create Request",
+ "description": "",
+ "type": "object",
+ "properties": {
+ "description": {
+ "$ref": "registration-token#/definitions/description"
+ },
+ "siteAreaID": {
+ "$ref": "registration-token#/definitions/siteAreaID"
+ },
+ "expirationDate": {
+ "$ref": "registration-token#/definitions/expirationDate"
+ }
+ },
+ "required": [
+ "description"
+ ]
+}

ADD
src/assets/server/rest/v1/schemas/registration-token/registration-token-update.json
+{
+ "$id": "registration-token-update",
+ "title": "Registration Token update Request",
+ "description": "",
+ "type": "object",
+ "properties": {
+ "id": {
+ "$ref": "registration-token#/definitions/id"
+ },
+ "description": {
+ "$ref": "registration-token#/definitions/description"
+ },
+ "siteAreaID": {
+ "$ref": "registration-token#/definitions/siteAreaID"
+ },
+ "expirationDate": {
+ "$ref": "registration-token#/definitions/expirationDate"
+ }
+ },
+ "required": [
+ "id",
+ "description"
+ ]
+}

ADD
src/assets/server/rest/v1/schemas/registration-token/registration-tokens-get.json
+{
+ "$id": "registration-tokens-get",
+ "title": "Registration Tokens get Request",
+ "description": "",
+ "type": "object",
+ "properties": {
+ "SiteAreaID": {
+ "$ref": "registration-token#/definitions/siteAreaID"
+ },
+ "Limit": {
+ "$ref": "common#/definitions/limit"
+ },
+ "SortFields": {
+ "$ref": "common#/definitions/sortFields"
+ },
+ "Skip": {
+ "$ref": "common#/definitions/skip"
+ },
+ "OnlyRecordCount": {
+ "$ref": "common#/definitions/onlyRecordCount"
+ },
+ "ProjectFields": {
+ "$ref": "common#/definitions/projectFields"
+ }
+ },
+ "required": [
+ "Limit"
+ ]
+}

MODIFY
src/server/rest/v1/service/RegistrationTokenService.ts
src/server/rest/v1/service/RegistrationTokenService.ts
@@ -9,8 +9,8 @@ import Authorizations from '../../../../authorization/Authorizations';
import Constants from '../../../../utils/Constants';
import Logging from '../../../../utils/Logging';
import RegistrationToken from '../../../../types/RegistrationToken';
-import RegistrationTokenSecurity from './security/RegistrationTokenSecurity';
import RegistrationTokenStorage from '../../../../storage/mongodb/RegistrationTokenStorage';
+import RegistrationTokenValidator from '../validator/RegistrationTokenValidator';
import { ServerAction } from '../../../../types/Server';
import SiteAreaStorage from '../../../../storage/mongodb/SiteAreaStorage';
import { TenantComponents } from '../../../../types/Tenant';
@@ -23,7 +23,7 @@ const MODULE_NAME = 'RegistrationTokenService';
export default class RegistrationTokenService {
static async handleCreateRegistrationToken(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
// Filter
- const filteredRequest = RegistrationTokenSecurity.filterRegistrationTokenCreateRequest(req.body);
+ const filteredRequest = RegistrationTokenValidator.getInstance().validateRegistrationTokenCreateReq(req.body);
// Check Auth
if (Utils.isComponentActiveFromToken(req.user, TenantComponents.ORGANIZATION) && filteredRequest.siteAreaID) {
// Get the Site Area
@@ -89,8 +89,7 @@ export default class RegistrationTokenService {
static async handleUpdateRegistrationToken(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
// Filter
- const filteredRequest = RegistrationTokenSecurity.filterRegistrationTokenUpdateRequest(req.body);
- UtilsService.assertIdIsProvided(action, filteredRequest.id, MODULE_NAME, 'handleUpdateRegistrationToken', req.user);
+ const filteredRequest = RegistrationTokenValidator.getInstance().validateRegistrationTokenUpdateReq(req.body);
// Check Auth
if (!await Authorizations.canUpdateRegistrationToken(req.user, filteredRequest.siteAreaID)) {
// Not Authorized!
@@ -141,8 +140,7 @@ export default class RegistrationTokenService {
}
static async handleDeleteRegistrationToken(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
- const tokenID = RegistrationTokenSecurity.filterRegistrationTokenByIDRequest(req.query);
- UtilsService.assertIdIsProvided(action, tokenID, MODULE_NAME, 'handleDeleteRegistrationToken', req.user);
+ const tokenID = RegistrationTokenValidator.getInstance().validateRegistrationTokenGetReq(req.query).ID;
// Get Token
const registrationToken = await RegistrationTokenStorage.getRegistrationToken(req.tenant, tokenID);
UtilsService.assertObjectExists(action, registrationToken, `Registration Token ID '${tokenID}' does not exist`,
@@ -173,8 +171,7 @@ export default class RegistrationTokenService {
}
static async handleRevokeRegistrationToken(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
- const tokenID = RegistrationTokenSecurity.filterRegistrationTokenByIDRequest(req.query);
- UtilsService.assertIdIsProvided(action, tokenID, MODULE_NAME, 'handleDeleteRegistrationToken', req.user);
+ const tokenID = RegistrationTokenValidator.getInstance().validateRegistrationTokenGetReq(req.query).ID;
// Get Token
const registrationToken = await RegistrationTokenStorage.getRegistrationToken(req.tenant, tokenID);
UtilsService.assertObjectExists(action, registrationToken, `Registration Token ID '${tokenID}' does not exist`,
@@ -227,7 +224,7 @@ export default class RegistrationTokenService {
module: MODULE_NAME, method: 'handleGetRegistrationTokens'
});
}
- const filteredRequest = RegistrationTokenSecurity.filterRegistrationTokensRequest(req.query);
+ const filteredRequest = RegistrationTokenValidator.getInstance().validateRegistrationTokensGetReq(req.query);
// Check User
let userProject: string[] = [];
if ((await Authorizations.canListUsers(req.user)).authorized) {
@@ -242,7 +239,7 @@ export default class RegistrationTokenService {
{
limit: filteredRequest.Limit,
skip: filteredRequest.Skip,
- sort: filteredRequest.SortFields,
+ sort: UtilsService.httpSortFieldsToMongoDB(filteredRequest.SortFields),
onlyRecordCount: filteredRequest.OnlyRecordCount
},
[
@@ -263,7 +260,7 @@ export default class RegistrationTokenService {
}
static async handleGetRegistrationToken(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
- const filteredRequest = RegistrationTokenSecurity.filterRegistrationTokenByIDRequest(req.query);
+ const filteredRequest = RegistrationTokenValidator.getInstance().validateRegistrationTokenGetReq(req.query).ID;
// Check User
let userProject: string[] = [];
if ((await Authorizations.canListUsers(req.user)).authorized) {

ADD
src/server/rest/v1/validator/RegistrationTokenValidator.ts
+import { HttpRegistrationTokenRequest, HttpRegistrationTokensRequest } from '../../../../types/requests/HttpRegistrationToken';
+
+import RegistrationToken from '../../../../types/RegistrationToken';
+import Schema from '../../../../types/validator/Schema';
+import SchemaValidator from '../../../../validator/SchemaValidator';
+import fs from 'fs';
+import global from '../../../../types/GlobalType';
+
+export default class RegistrationTokenValidator extends SchemaValidator {
+ private static instance: RegistrationTokenValidator | null = null;
+ private registrationTokenCreate: Schema;
+ private registrationTokenGetByID: Schema;
+ private registrationTokensGet: Schema;
+ private registrationTokenUpdate: Schema;
+
+
+ private constructor() {
+ super('RegistrationTokenValidator');
+ this.registrationTokenCreate = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/registration-token/registration-token-create.json`, 'utf8'));
+ this.registrationTokenGetByID = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/registration-token/registration-token-by-id.json`, 'utf8'));
+ this.registrationTokensGet = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/registration-token/registration-tokens-get.json`, 'utf8'));
+ this.registrationTokenUpdate = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/registration-token/registration-token-update.json`, 'utf8'));
+ }
+
+ public static getInstance(): RegistrationTokenValidator {
+ if (!RegistrationTokenValidator.instance) {
+ RegistrationTokenValidator.instance = new RegistrationTokenValidator();
+ }
+ return RegistrationTokenValidator.instance;
+ }
+
+ public validateRegistrationTokenCreateReq(data: Record<string, unknown>): RegistrationToken {
+ return this.validate(this.registrationTokenCreate, data as unknown as Record<string, unknown>);
+ }
+
+ public validateRegistrationTokenGetReq(data: Record<string, unknown>): HttpRegistrationTokenRequest {
+ return this.validate(this.registrationTokenGetByID, data as unknown as Record<string, unknown>);
+ }
+
+ public validateRegistrationTokensGetReq(data: Record<string, unknown>): HttpRegistrationTokensRequest {
+ return this.validate(this.registrationTokensGet, data as unknown as Record<string, unknown>);
+ }
+
+ public validateRegistrationTokenUpdateReq(data: Record<string, unknown>): RegistrationToken {
+ return this.validate(this.registrationTokenUpdate, data as unknown as Record<string, unknown>);
+ }
+}

MODIFY
src/storage/mongodb/RegistrationTokenStorage.ts
src/storage/mongodb/RegistrationTokenStorage.ts
@@ -22,7 +22,7 @@ export default class RegistrationTokenStorage {
const registrationTokenMDB = {
_id: registrationToken.id ? DatabaseUtils.convertToObjectID(registrationToken.id) : new ObjectId(),
description: registrationToken.description,
- siteAreaID: DatabaseUtils.convertToObjectID(registrationToken.siteAreaID),
+ siteAreaID: registrationToken.siteAreaID ? DatabaseUtils.convertToObjectID(registrationToken.siteAreaID) : null,
expirationDate: Utils.convertToDate(registrationToken.expirationDate),
revocationDate: Utils.convertToDate(registrationToken.revocationDate)
};

MODIFY
src/types/requests/HttpRegistrationToken.ts
src/types/requests/HttpRegistrationToken.ts
+import HttpByIDRequest from './HttpByIDRequest';
import HttpDatabaseRequest from './HttpDatabaseRequest';
import RegistrationToken from '../RegistrationToken';
@@ -5,6 +6,10 @@ export interface HttpRegistrationTokensRequest extends HttpDatabaseRequest {
SiteAreaID: string;
}
+export interface HttpRegistrationTokenRequest extends HttpByIDRequest {
+ ID: string;
+}
+
export interface HttpRegistrationTokensResponse {
count: number;
result: RegistrationToken[];

MODIFY
src/validator/SchemaValidator.ts
src/validator/SchemaValidator.ts
@@ -29,6 +29,7 @@ export default class SchemaValidator {
private static assetSchema: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/schemas/asset/asset.json`, 'utf8'));
private static companySchema: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/schemas/company/company.json`, 'utf8'));
private static ocpiEndpointSchema: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/schemas/ocpi/ocpi-endpoint.json`, 'utf8'));
+ private static registrationTokenSchema: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/schemas/registration-token/registration-token.json`, 'utf8'));
private readonly ajv: Ajv;
constructor(readonly moduleName: string,
@@ -52,17 +53,20 @@ export default class SchemaValidator {
// Add custom Formatter
this.addCustomFormatters();
// Add common schema
- this.ajv.addSchema(SchemaValidator.commonSchema);
- this.ajv.addSchema(SchemaValidator.tenantSchema);
- this.ajv.addSchema(SchemaValidator.tenantComponentSchema);
- this.ajv.addSchema(SchemaValidator.chargingStationSchema);
- this.ajv.addSchema(SchemaValidator.tagSchema);
- this.ajv.addSchema(SchemaValidator.transactionSchema);
- this.ajv.addSchema(SchemaValidator.userSchema);
- this.ajv.addSchema(SchemaValidator.carSchema);
- this.ajv.addSchema(SchemaValidator.assetSchema);
- this.ajv.addSchema(SchemaValidator.companySchema);
- this.ajv.addSchema(SchemaValidator.ocpiEndpointSchema);
+ this.ajv.addSchema([
+ SchemaValidator.commonSchema,
+ SchemaValidator.tenantSchema,
+ SchemaValidator.tenantComponentSchema,
+ SchemaValidator.chargingStationSchema,
+ SchemaValidator.tagSchema,
+ SchemaValidator.transactionSchema,
+ SchemaValidator.userSchema,
+ SchemaValidator.carSchema,
+ SchemaValidator.assetSchema,
+ SchemaValidator.companySchema,
+ SchemaValidator.ocpiEndpointSchema,
+ SchemaValidator.registrationTokenSchema
+ ]);
}
protected validate(schema: Schema, data: Record<string, unknown>): any {

Added registration tokens JSON schema validation