Refuse unknown settings
MODIFY
src/assets/server/rest/v1/schemas/setting/setting-analytics-set.json
src/assets/server/rest/v1/schemas/setting/setting-analytics-set.json
"identifier": {
"type": "string",
"sanitize": "mongo",
- "enum": ["sac"]
+ "enum": ["analytics"]
},
"sensitiveData": {
"$ref": "setting#/definitions/sensitiveData"

MODIFY
src/assets/server/rest/v1/schemas/setting/setting-billing-set.json
src/assets/server/rest/v1/schemas/setting/setting-billing-set.json
"type": {
"type": "string",
"sanitize": "mongo",
- "enum": ["billing"]
+ "enum": ["stripe"]
}
},
"required": [

ADD
src/assets/server/rest/v1/schemas/setting/setting-car-set.json
+{
+ "$id": "setting-car-set",
+ "title": "Set Car Settings",
+ "type": "object",
+ "properties": {
+ "content": {
+ "type": "object",
+ "properties": {
+ "links": {
+ "$ref": "setting#/definitions/links"
+ }
+ }
+ },
+ "id": {
+ "$ref": "common#/definitions/id"
+ },
+ "identifier": {
+ "type": "string",
+ "sanitize": "mongo",
+ "enum": ["car"]
+ },
+ "sensitiveData": {
+ "$ref": "setting#/definitions/sensitiveData"
+ }
+ },
+ "required": [
+ "identifier"
+ ]
+}

ADD
src/assets/server/rest/v1/schemas/setting/setting-organization-set.json
+{
+ "$id": "setting-organization-set",
+ "title": "Set Organization Settings",
+ "type": "object",
+ "properties": {
+ "content": {
+ "type": "object",
+ "properties": {
+ "links": {
+ "$ref": "setting#/definitions/links"
+ }
+ }
+ },
+ "id": {
+ "$ref": "common#/definitions/id"
+ },
+ "identifier": {
+ "type": "string",
+ "sanitize": "mongo",
+ "enum": ["organization"]
+ },
+ "sensitiveData": {
+ "$ref": "setting#/definitions/sensitiveData"
+ }
+ },
+ "required": [
+ "identifier"
+ ]
+}

ADD
src/assets/server/rest/v1/schemas/setting/setting-statistics-set.json
+{
+ "$id": "setting-statistics-set",
+ "title": "Set Statistics Settings",
+ "type": "object",
+ "properties": {
+ "content": {
+ "type": "object",
+ "properties": {
+ "links": {
+ "$ref": "setting#/definitions/links"
+ }
+ }
+ },
+ "id": {
+ "$ref": "common#/definitions/id"
+ },
+ "identifier": {
+ "type": "string",
+ "sanitize": "mongo",
+ "enum": ["statistics"]
+ },
+ "sensitiveData": {
+ "$ref": "setting#/definitions/sensitiveData"
+ }
+ },
+ "required": [
+ "identifier"
+ ]
+}

MODIFY
src/server/rest/v1/service/SettingService.ts
src/server/rest/v1/service/SettingService.ts
import { Action, Entity } from '../../../../types/Authorization';
import { HTTPAuthError, HTTPError } from '../../../../types/HTTPError';
-import { IntegrationSettings, TechnicalSettings } from '../../../../types/Setting';
+import { IntegrationSettings, SettingDB, TechnicalSettings } from '../../../../types/Setting';
import { NextFunction, Request, Response } from 'express';
import AppAuthError from '../../../../exception/AppAuthError';
@@ -151,7 +151,7 @@ export default class SettingService {
});
}
// Filter
- const filteredRequest = await SettingService.filterSetting(action, req, true);
+ const filteredRequest = SettingService.filterSetting(action, req) as SettingDB;
// Process the sensitive data if any
await Cypher.encryptSensitiveDataInJSON(req.tenant, filteredRequest);
// Update timestamp
@@ -173,7 +173,7 @@ export default class SettingService {
public static async handleUpdateSetting(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
UtilsService.assertIdIsProvided(action, req.body.id, MODULE_NAME, 'handleUpdateSetting', req.user);
- const filteredRequest = await SettingService.filterSetting(action, req, false);
+ const filteredRequest = SettingService.filterSetting(action, req) as SettingDB;
// Check auth
if (!await Authorizations.canUpdateSetting(req.user)) {
throw new AppAuthError({
@@ -186,7 +186,7 @@ export default class SettingService {
}
// Get Setting
const setting = await SettingStorage.getSetting(req.tenant, filteredRequest.id);
- UtilsService.assertObjectExists(action, setting, `Setting ID '${filteredRequest.id as string}' does not exist`,
+ UtilsService.assertObjectExists(action, setting, `Setting ID '${filteredRequest.id }' does not exist`,
MODULE_NAME, 'handleUpdateSetting', req.user);
// Process the sensitive data if any
// Preprocess the data to take care of updated values
@@ -194,7 +194,7 @@ export default class SettingService {
if (!Array.isArray(filteredRequest.sensitiveData)) {
throw new AppError({
errorCode: HTTPError.CYPHER_INVALID_SENSITIVE_DATA_ERROR,
- message: `The property 'sensitiveData' for Setting with ID '${filteredRequest.id as string}' is not an array`,
+ message: `The property 'sensitiveData' for Setting with ID '${filteredRequest.id }' is not an array`,
module: MODULE_NAME,
method: 'handleUpdateSetting',
user: req.user
@@ -288,7 +288,7 @@ export default class SettingService {
await Logging.logInfo({
tenantID: req.user.tenantID,
user: req.user, module: MODULE_NAME, method: 'handleUpdateSetting',
- message: `Setting '${filteredRequest.id as string}' has been updated successfully`,
+ message: `Setting '${filteredRequest.id}' has been updated successfully`,
action: action,
detailedMessages: { filteredRequest }
});
@@ -296,8 +296,7 @@ export default class SettingService {
next();
}
- private static async filterSetting(action: ServerAction, req: Request, createSetting: boolean) {
- let filteredRequest;
+ private static filterSetting(action: ServerAction, req: Request) {
switch (req.body.identifier) {
// Filter
case IntegrationSettings.OCPI:
@@ -314,24 +313,29 @@ export default class SettingService {
return SettingValidator.getInstance().validateSettingRefundSetReq(req.body);
case IntegrationSettings.PRICING:
return SettingValidator.getInstance().validateSettingPricingSetReq(req.body);
- case IntegrationSettings.SAC:
+ case IntegrationSettings.ANALYTICS:
return SettingValidator.getInstance().validateSettingAnalyticsSetReq(req.body);
case IntegrationSettings.ASSET:
return SettingValidator.getInstance().validateSettingAssetSetReq(req.body);
+ case IntegrationSettings.CAR_CONNECTOR:
+ return SettingValidator.getInstance().validateSettingCarConnectorSetReq(req.body);
+ case IntegrationSettings.BILLING:
+ return SettingValidator.getInstance().validateSettingBillingSetReq(req.body);
+ case IntegrationSettings.CAR:
+ return SettingValidator.getInstance().validateSettingCarSetReq(req.body);
+ case IntegrationSettings.ORGANIZATION:
+ return SettingValidator.getInstance().validateSettingOrganizationSetReq(req.body);
+ case IntegrationSettings.STATISTICS:
+ return SettingValidator.getInstance().validateSettingStatisticsSetReq(req.body);
default:
- if (createSetting) {
- filteredRequest = SettingSecurity.filterSettingCreateRequest(req.body);
- } else {
- filteredRequest = SettingSecurity.filterSettingUpdateRequest(req.body);
- }
- await Logging.logDebug({
- tenantID: req.user.tenantID,
- user: req.user, module: MODULE_NAME, method: 'filterSetting',
- message: `The property 'identifier' with value '${req.body.identifier as string}' for Setting with ID '${req.body.id as string}' has no dedicated schema (yet)`,
- action: action,
- detailedMessages: { filteredRequest }
+ throw new AppError({
+ module: MODULE_NAME,
+ method: 'filterSetting',
+ action,
+ message: `Unknown setting ${req.body.identifier as string}`,
+ detailedMessages: { setting: req.body },
+ errorCode: HTTPError.GENERAL_ERROR
});
- return filteredRequest;
}
}
}

MODIFY
src/server/rest/v1/service/TenantService.ts
src/server/rest/v1/service/TenantService.ts
@@ -288,7 +288,7 @@ export default class TenantService {
'/verify-email?VerificationToken=' + verificationToken + '&Email=' +
tenantUser.email + '&ResetToken=' + resetHash;
// Send Register User (Async)
- await NotificationHandler.sendNewRegisteredUser(
+ NotificationHandler.sendNewRegisteredUser(
tenant,
Utils.generateUUID(),
tenantUser,

MODIFY
src/server/rest/v1/validator/SettingValidator.ts
src/server/rest/v1/validator/SettingValidator.ts
@@ -18,6 +18,9 @@ export default class SettingValidator extends SchemaValidator {
private settingBillingSet: Schema;
private settingAssetSet: Schema;
private settingCarConnectorSet: Schema;
+ private settingCarSet: Schema;
+ private settingOrganizationSet: Schema;
+ private settingStatisticsSet: Schema;
private constructor() {
super('SettingValidator');
@@ -32,6 +35,9 @@ export default class SettingValidator extends SchemaValidator {
this.settingBillingSet = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/setting/setting-billing-set.json`, 'utf8'));
this.settingAssetSet = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/setting/setting-asset-set.json`, 'utf8'));
this.settingCarConnectorSet = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/setting/setting-car-connector-set.json`, 'utf8'));
+ this.settingCarSet = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/setting/setting-car-set.json`, 'utf8'));
+ this.settingOrganizationSet = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/setting/setting-organization-set.json`, 'utf8'));
+ this.settingStatisticsSet = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/setting/setting-statistics-set.json`, 'utf8'));
}
public static getInstance(): SettingValidator {
@@ -84,4 +90,16 @@ export default class SettingValidator extends SchemaValidator {
public validateSettingCarConnectorSetReq(data: Record<string, unknown>): HttpSettingCarConnectorSetRequest {
return this.validate(this.settingCarConnectorSet, data);
}
+
+ public validateSettingCarSetReq(data: Record<string, unknown>) {
+ return this.validate(this.settingCarSet, data);
+ }
+
+ public validateSettingOrganizationSetReq(data: Record<string, unknown>) {
+ return this.validate(this.settingOrganizationSet, data);
+ }
+
+ public validateSettingStatisticsSetReq(data: Record<string, unknown>) {
+ return this.validate(this.settingStatisticsSet, data);
+ }
}

MODIFY
src/types/Setting.ts
src/types/Setting.ts
@@ -9,11 +9,16 @@ export enum TechnicalSettings {
export enum IntegrationSettings {
OCPI = 'ocpi',
OICP = 'oicp',
- SAC = 'sapAnalytics',
+ ANALYTICS = 'analytics',
SMART_CHARGING = 'smartCharging',
REFUND = 'refund',
PRICING = 'pricing',
- ASSET = 'asset'
+ ASSET = 'asset',
+ CAR_CONNECTOR = 'carConnector',
+ BILLING = 'billing',
+ CAR = 'car',
+ ORGANIZATION = 'organization',
+ STATISTICS = 'statistics'
}
export interface Setting extends CreatedUpdatedProps {

Refuse unknown settings