Skip to content

Commit

Permalink
Merge pull request #103 from rdkcentral/FIRECERT-2025
Browse files Browse the repository at this point in the history
FIRECERT-2025: Migrate schema validation to FCS
  • Loading branch information
Abhishk123 authored Jul 1, 2024
2 parents 5490206 + 7460bc8 commit 83ef134
Show file tree
Hide file tree
Showing 15 changed files with 342 additions and 713 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Mode of execution implies the way in which an API is invoked. There are 2 modes
- Steps to convert into `html report`
1. Move the `json report` to root folder
2. Run the command `yarn marge filename.json -f report -o /destination_path`
3. Check the `html report` on the destination path.
3. Check the `html report` on the destination path

## Supported Report Parameters

Expand Down Expand Up @@ -154,4 +154,3 @@ The prompt is displayed when the user needs to grant/deny a particular api, or t
If user wants to grant an api, yes button is pressed, for deniel - no button, and incase if the user wants to dismiss the prompt without any action, back button is pressed.



1 change: 1 addition & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ export default class App extends Base {
process.env.REPORTINGID = reportingId;
process.env.STANDALONE = standalone;
process.env.STANDALONE_PREFIX = standalonePrefix;
process.env.ID = 0;
process.env.REGISTERPROVIDER = true;

// Set the pubSub URL if present
Expand Down
125 changes: 79 additions & 46 deletions src/EventInvocation.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ class EventHandler {
this.moduleWithEventName = moduleWithEventName;
const event = moduleWithEventName.split('.')[1];
this.eventName = this.parseEventName(event);
this.eventSchema = this.getSchema(moduleWithEventName, schemaList);
if (process.env.STANDALONE == true) {
this.eventSchema = this.getSchema(moduleWithEventName, schemaList);
}
this.initializationTime = new Date();
this.eventListener = null;
}
Expand Down Expand Up @@ -67,16 +69,27 @@ class EventHandler {
}
return schemaMap;
}

// Handle, parse and store the resolved event data from listener
handleEvent(eventData) {
const eventSchemaResponse = this.eventSchemaValidation(eventData);
const eventDataObject = {
eventName: this.eventName,
eventListenerId: this.eventListener.eventListenerId,
eventResponse: eventData,
eventSchemaResult: eventSchemaResponse,
eventTime: new Date(),
};
let eventDataObject;
if (process.env.STANDALONE == true) {
const eventSchemaResponse = this.eventSchemaValidation(eventData);
eventDataObject = {
eventName: this.eventName,
eventListenerId: this.eventListener.eventListenerId,
eventResponse: eventData,
eventSchemaResult: eventSchemaResponse,
eventTime: new Date(),
};
} else {
eventDataObject = {
eventName: this.eventName,
eventListenerId: this.eventListener.id,
eventResponse: eventData,
eventTime: new Date(),
};
}
eventHistory.push(eventDataObject);
}
// Schema validation for resolved event data
Expand Down Expand Up @@ -107,53 +120,68 @@ class EventHandler {
export class EventInvocation {
// This method accepts the message params and return the listener response and schema response
async northBoundEventHandling(message) {
let responseCode;
const eventParams = message.params;
const moduleWithEventName = eventParams.event;
const params = eventParams.params;
const [listenerResponse, uniqueListenerKey] = await this.registerEvent(moduleWithEventName, params);

const registrationResponse = {};
registrationResponse['eventName'] = moduleWithEventName;
registrationResponse['eventListenerId'] = uniqueListenerKey;
if (listenerResponse && Number.isInteger(listenerResponse) && listenerResponse > 0) {
registrationResponse['eventListenerResponse'] = {
listenerResponse: listenerResponse,
error: null,
};
// Handling not supported api to check error schema if it gives a valid response
let schemaValidationResult = {};
let schemaValidationStatus = CONSTANTS.PASS;
if (message.params.isNotSupportedApi == true) {
schemaValidationResult = errorSchemaCheck(listenerResponse, process.env.COMMUNICATION_MODE);
schemaValidationStatus = CONSTANTS.FAIL;
}
registrationResponse['eventListenerSchemaResult'] = {
status: schemaValidationStatus,
eventSchemaResult: schemaValidationResult,
};
eventHandlerMap.get(uniqueListenerKey).setEventListener(registrationResponse);
} else {
if (CONSTANTS.ERROR_LIST.includes(listenerResponse.message)) {
responseCode = CONSTANTS.STATUS_CODE[3];
registrationResponse['responseCode'] = responseCode;
}
registrationResponse['eventListenerResponse'] = { result: null, error: listenerResponse };
// In case of error, validate error against errorschema
const schemaValidationResult = errorSchemaCheck(listenerResponse, process.env.COMMUNICATION_MODE);
if (schemaValidationResult && schemaValidationResult.errors && schemaValidationResult.errors.length > 0) {
registrationResponse['eventListenerSchemaResult'] = {
status: CONSTANTS.FAIL,
eventSchemaResult: {},

if (process.env.STANDALONE == true) {
registrationResponse['eventName'] = moduleWithEventName;
registrationResponse['eventListenerId'] = uniqueListenerKey;
if (listenerResponse && Number.isInteger(listenerResponse) && listenerResponse > 0) {
registrationResponse['eventListenerResponse'] = {
listenerResponse: listenerResponse,
error: null,
};
} else {
// Handling not supported api to check error schema if it gives a valid response
let schemaValidationResult = {};
let schemaValidationStatus = CONSTANTS.PASS;
if (message.params.isNotSupportedApi == true) {
schemaValidationResult = errorSchemaCheck(listenerResponse, process.env.COMMUNICATION_MODE);
schemaValidationStatus = CONSTANTS.FAIL;
}
registrationResponse['eventListenerSchemaResult'] = {
status: CONSTANTS.PASS,
status: schemaValidationStatus,
eventSchemaResult: schemaValidationResult,
};
eventHandlerMap.get(uniqueListenerKey).setEventListener(registrationResponse);
} else {
if (CONSTANTS.ERROR_LIST.includes(listenerResponse.message)) {
const responseCode = CONSTANTS.STATUS_CODE[3];
registrationResponse['responseCode'] = responseCode;
}
registrationResponse['eventListenerResponse'] = { result: null, error: listenerResponse };
// In case of error, validate error against errorschema
const schemaValidationResult = errorSchemaCheck(listenerResponse, process.env.COMMUNICATION_MODE);
if (schemaValidationResult && schemaValidationResult.errors && schemaValidationResult.errors.length > 0) {
registrationResponse['eventListenerSchemaResult'] = {
status: CONSTANTS.FAIL,
eventSchemaResult: {},
};
} else {
registrationResponse['eventListenerSchemaResult'] = {
status: CONSTANTS.PASS,
eventSchemaResult: schemaValidationResult,
};
}
}
return registrationResponse;
} else {
registrationResponse['jsonrpc'] = '2.0';
registrationResponse['id'] = null;
if (listenerResponse && Number.isInteger(listenerResponse) && listenerResponse > 0) {
registrationResponse['id'] = listenerResponse;
registrationResponse['result'] = {
listening: true,
event: moduleWithEventName,
};
eventHandlerMap.get(uniqueListenerKey).setEventListener(registrationResponse);
} else {
registrationResponse['error'] = listenerResponse;
}
return registrationResponse;
}
return registrationResponse;
}

// This method will listen to event and capture the event response after triggering
Expand Down Expand Up @@ -298,8 +326,13 @@ export class EventInvocation {
// Return the event response object for the eventName passed as the param
getEventResponse(message) {
try {
let filteredEventDataObjectList;
const eventName = message.params.event;
const filteredEventDataObjectList = eventHistory.filter((element) => element.eventListenerId == eventName);
if (process.env.STANDALONE == true) {
filteredEventDataObjectList = eventHistory.filter((element) => element.eventListenerId == eventName);
} else {
filteredEventDataObjectList = eventHistory.filter((element) => element.eventListenerId.toString() == eventName.split('-').pop());
}
if (filteredEventDataObjectList.length) {
const eventDataObject = filteredEventDataObjectList[filteredEventDataObjectList.length - 1];
return eventDataObject;
Expand Down
40 changes: 27 additions & 13 deletions src/MethodInvoker.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,8 @@ const responseList = [];
export class MethodInvoker {
// This method accepts the message(method name, params) and return Api response with Schema validation result.
async invoke(message) {
let response, method, params, mode, err, paramNames, module, methodObj;
let schemaMap;
let schemaValidationResult;
let response, method, params, mode, err, paramNames, module, methodObj, schemaMap, schemaValidationResult;
process.env.ID = process.env.ID + 1;
process.env.COMMUNICATION_MODE = message.context.communicationMode;
params = message.params.methodParams;
if (message.params.method.includes('_')) {
Expand Down Expand Up @@ -70,12 +69,14 @@ export class MethodInvoker {
try {
// Fetching the method Object from the deSchemaList
if (method.includes('set') && params[0] == undefined && !CONSTANTS.METHODS_T0_IGNORE_WHICH_HAS_SET.includes(method)) {
methodObj = deSchemaList.methods.find((obj) => obj.name.toLowerCase() == updatedMethod.toLowerCase());
methodObj = deSchemaList.methods.some((obj) => obj.name.toLowerCase() == updatedMethod.toLowerCase());
} else {
methodObj = deSchemaList.methods.find((obj) => obj.name.toLowerCase() == method.toLowerCase());
methodObj = deSchemaList.methods.some((obj) => obj.name.toLowerCase() == method.toLowerCase());
}
if (methodObj) {
schemaMap = methodObj.result.schema;
if (process.env.STANDALONE == true) {
schemaMap = methodObj.result.schema;
}
const moduleClass = MODULE_MAP[invokedSdk][module];

if (moduleClass) {
Expand All @@ -88,16 +89,22 @@ export class MethodInvoker {
} else if (process.env.COMMUNICATION_MODE === CONSTANTS.TRANSPORT) {
[response, err] = await handleAsyncFunction(FireboltTransportInvoker.get().invoke(method, params, paramNames), process.env.TimeoutInMS);
}
schemaValidationResult = validator.validate(response, schemaMap);
if (process.env.STANDALONE == true) {
schemaValidationResult = validator.validate(response, schemaMap);
}
} else if (!methodObj && process.env.COMMUNICATION_MODE === CONSTANTS.TRANSPORT) {
[response, err] = await handleAsyncFunction(FireboltTransportInvoker.get().invoke(method, params, paramNames), process.env.TimeoutInMS);
schemaValidationResult = [];
if (process.env.STANDALONE == true) {
schemaValidationResult = [];
}
} else {
err = CONSTANTS.ERROR_MESSAGE_WRONG_METHOD_NAME;
}
// if the method is not supported and it gives a valid response, validate against errorschema instead of api schema
if (message.params.isNotSupportedApi == true && response != undefined) {
schemaValidationResult = errorSchemaCheck(response, process.env.COMMUNICATION_MODE);
if (process.env.STANDALONE == true) {
// if the method is not supported and it gives a valid response, validate against errorschema instead of api schema
if (message.params.isNotSupportedApi == true && response != undefined) {
schemaValidationResult = errorSchemaCheck(response, process.env.COMMUNICATION_MODE);
}
}
} catch (error) {
logger.error('Error: ', error);
Expand All @@ -113,8 +120,15 @@ export class MethodInvoker {
},
};
responseList.push(resultObject);

return this.formatResult(message.task, response, err, schemaValidationResult, params, schemaMap);
if (process.env.STANDALONE == true) {
return this.formatResult(message.task, response, err, schemaValidationResult, params, schemaMap);
} else {
if (err === undefined) {
return { jsonrpc: '2.0', result: response, id: process.env.ID };
} else {
return { jsonrpc: '2.0', error: err, id: process.env.ID };
}
}
}

formatResult(task, response, err, schemaValidationResult, params, schemaMap) {
Expand Down
Loading

0 comments on commit 83ef134

Please sign in to comment.