Skip to content

Commit

Permalink
Merge pull request #242 from Sanketika-Obsrv/dataset-audit
Browse files Browse the repository at this point in the history
#OBS-I165: Dataset audit using user token
  • Loading branch information
HarishGangula authored Sep 16, 2024
2 parents b90f378 + aaef037 commit 593cae6
Show file tree
Hide file tree
Showing 17 changed files with 276 additions and 181 deletions.
10 changes: 9 additions & 1 deletion api-service/src/controllers/Alerts/Alerts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ const telemetryObject = { type: "alert", ver: "1.0.0" };
const createAlertHandler = async (req: Request, res: Response, next: NextFunction) => {
try {
const alertPayload = getAlertPayload(req.body);
const userID = (req as any)?.userID;
_.set(alertPayload, "created_by", userID);
const response = await Alert.create(alertPayload);
updateTelemetryAuditEvent({ request: req, object: { id: response?.dataValues?.id, ...telemetryObject } });
ResponseHandler.successResponse(req, res, { status: httpStatus.OK, data: { id: response.dataValues.id } });
Expand All @@ -30,6 +32,8 @@ const publishAlertHandler = async (req: Request, res: Response, next: NextFuncti
const { alertId } = req.params;
const rulePayload: Record<string, any> | null = await getAlertRule(alertId);
if (!rulePayload) return next({ message: httpStatus[httpStatus.NOT_FOUND], statusCode: httpStatus.NOT_FOUND });
const userID = (req as any)?.userID;
_.set(rulePayload, "updated_by", userID);
if (rulePayload.status == "live") {
await deleteAlertRule(rulePayload, false);
}
Expand Down Expand Up @@ -87,6 +91,8 @@ const deleteAlertHandler = async (req: Request, res: Response, next: NextFunctio
return next({ message: httpStatus[httpStatus.NOT_FOUND], statusCode: httpStatus.NOT_FOUND });
}
const rulePayload = ruleModel.toJSON();
const userID = (req as any)?.userID || "SYSTEM";
_.set(rulePayload, "updated_by", userID);
await deleteAlertRule(rulePayload, hardDelete === "true");
updateTelemetryAuditEvent({ request: req, currentRecord: rulePayload, object: { id: alertId, ...telemetryObject } });
ResponseHandler.successResponse(req, res, { status: httpStatus.OK, data: { id: alertId } });
Expand All @@ -103,12 +109,14 @@ const updateAlertHandler = async (req: Request, res: Response, next: NextFunctio
const ruleModel = await getAlertRule(alertId);
if (!ruleModel) { return next({ message: httpStatus[httpStatus.NOT_FOUND], statusCode: httpStatus.NOT_FOUND }) }
const rulePayload = ruleModel.toJSON();
const userID = (req as any)?.userID;
if (rulePayload.status == "live") {
_.set(rulePayload, "updated_by", userID);
await deleteAlertRule(rulePayload, false);
await retireAlertSilence(alertId);
}
const updatedPayload = getAlertPayload({ ...req.body, manager: rulePayload?.manager });
await Alert.update({ ...updatedPayload, status: "draft" }, { where: { id: alertId } });
await Alert.update({ ...updatedPayload, status: "draft", updated_by: userID }, { where: { id: alertId } });
updateTelemetryAuditEvent({ request: req, currentRecord: rulePayload, object: { id: alertId, ...telemetryObject } });
ResponseHandler.successResponse(req, res, { status: httpStatus.OK, data: { id: alertId } });
} catch (error: any) {
Expand Down
6 changes: 5 additions & 1 deletion api-service/src/controllers/Alerts/Silence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ const createHandler = async (request: Request, response: Response, next: NextFun

const start_date = new Date(startDate);
const end_date = new Date(endDate);
const userID = (request as any)?.userID;
const silenceBody = {
id: grafanaResponse.silenceId,
manager: grafanaResponse.manager,
alert_id: alertId,
start_time: start_date,
end_time: end_date,
created_by : userID,
}
const sileneResponse = await Silence.create(silenceBody);
updateTelemetryAuditEvent({ request, object: { id: sileneResponse?.dataValues?.id, ...telemetryObject } });
Expand Down Expand Up @@ -78,10 +80,12 @@ const updateHandler = async (request: Request, response: Response, next: NextFun
await updateSilence(silenceObject, payload);
const updatedStartTime = new Date(payload.startTime);
const updatedEndTime = new Date(payload.endTime);
const userID = (request as any)?.userID;
const updatedSilence = {
...silenceObject,
start_time: updatedStartTime,
end_time: updatedEndTime
end_time: updatedEndTime,
updated_by: userID,
}
const silenceResponse = await Silence.update(updatedSilence, { where: { id } })
ResponseHandler.successResponse(request, response, { status: httpStatus.OK, data: { silenceResponse } })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ export const createQueryTemplate = async (req: Request, res: Response) => {
}

const data = transformRequest(requestBody, templateName);
const userID = (req as any)?.userID;
_.set(data, "created_by", userID);
await QueryTemplate.create(data)
logger.info({ apiId, msgid, resmsgid, requestBody: req?.body, message: `Query template created successfully` })
return ResponseHandler.successResponse(req, res, { status: 200, data: { template_id: templateId, template_name: templateName, message: `The query template has been saved successfully` } });
Expand Down
2 changes: 2 additions & 0 deletions api-service/src/controllers/DatasetCopy/DatasetCopy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ const datasetCopy = async (req: Request, res: Response) => {
validateRequest(req);
const newDatasetId = _.get(req, "body.request.destination.datasetId");
const dataset = await fetchDataset(req);
const userID = (req as any)?.userID;
_.set(dataset, "created_by", userID);
updateRecords(dataset, newDatasetId)
const response = await datasetService.createDraftDataset(dataset).catch(err => {
if (err?.name === "SequelizeUniqueConstraintError") {
Expand Down
2 changes: 2 additions & 0 deletions api-service/src/controllers/DatasetCreate/DatasetCreate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ const datasetCreate = async (req: Request, res: Response) => {

await validateRequest(req)
const draftDataset = getDraftDataset(req.body.request)
const userID = (req as any)?.userID;
_.set(draftDataset, "created_by", userID);
const dataset = await datasetService.createDraftDataset(draftDataset);
ResponseHandler.successResponse(req, res, { status: httpStatus.OK, data: dataset });
}
Expand Down
7 changes: 5 additions & 2 deletions api-service/src/controllers/DatasetImport/DatasetImport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,21 @@ const datasetImport = async (req: Request, res: Response) => {
const migratedConfigs = migrateExportedDatasetV1(requestBody)
datasetPayload = migratedConfigs;
}
const userID = (req as any)?.userID;
_.set(datasetPayload, "created_by", userID);
const { updatedDataset, ignoredFields } = await datasetImportValidation({ ...requestBody, "request": datasetPayload })
const { successMsg, partialIgnored } = getResponseData(ignoredFields)

const dataset = await importDataset(updatedDataset, overwrite);
const dataset = await importDataset(updatedDataset, overwrite, userID);
ResponseHandler.successResponse(req, res, { status: httpStatus.OK, data: { message: successMsg, data: dataset, ...(!_.isEmpty(partialIgnored) && { ignoredFields: partialIgnored }) } });
}

const importDataset = async (dataset: Record<string, any>, overwrite: string | any) => {
const importDataset = async (dataset: Record<string, any>, overwrite: string | any, userID : string) => {
const dataset_id = _.get(dataset,"dataset_id")
const response = await datasetService.createDraftDataset(dataset).catch(err => { return err })
if (response?.name === "SequelizeUniqueConstraintError") {
if (overwrite === "true") {
_.set(dataset, "updated_by", userID);
const overwriteRes = await datasetService.updateDraftDataset(dataset).catch(()=>{
throw obsrvError(dataset_id, "DATASET_IMPORT_FAILURE", `Failed to import dataset: ${dataset_id} as overwrite failed`, "INTERNAL_SERVER_ERROR", 500);
})
Expand Down
9 changes: 5 additions & 4 deletions api-service/src/controllers/DatasetRead/DatasetRead.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ const datasetRead = async (req: Request, res: Response) => {
validateRequest(req);
const { dataset_id } = req.params;
const { fields, mode } = req.query;
const userID = (req as any)?.userID;
const attributes = !fields ? defaultFields : _.split(<string>fields, ",");
const dataset = (mode == "edit") ? await readDraftDataset(dataset_id, attributes) : await readDataset(dataset_id, attributes)
const dataset = (mode == "edit") ? await readDraftDataset(dataset_id, attributes, userID) : await readDataset(dataset_id, attributes)
if (!dataset) {
throw obsrvError(dataset_id, "DATASET_NOT_FOUND", `Dataset with the given dataset_id:${dataset_id} not found`, "NOT_FOUND", 404);
}
Expand All @@ -41,19 +42,19 @@ const datasetRead = async (req: Request, res: Response) => {
ResponseHandler.successResponse(req, res, { status: httpStatus.OK, data: dataset });
}

const readDraftDataset = async (datasetId: string, attributes: string[]): Promise<any> => {
const readDraftDataset = async (datasetId: string, attributes: string[], userID: string): Promise<any> => {

const attrs = _.union(attributes, ["dataset_config", "api_version", "type", "id"])
const draftDataset = await datasetService.getDraftDataset(datasetId, attrs);
if (draftDataset) { // Contains a draft
const apiVersion = _.get(draftDataset, ["api_version"]);
const dataset: any = (apiVersion === "v2") ? draftDataset : await datasetService.migrateDraftDataset(datasetId, draftDataset)
const dataset: any = (apiVersion === "v2") ? draftDataset : await datasetService.migrateDraftDataset(datasetId, draftDataset, userID)
return _.pick(dataset, attributes);
}

const liveDataset = await datasetService.getDataset(datasetId, undefined, true);
if (liveDataset) {
const dataset = await datasetService.createDraftDatasetFromLive(liveDataset)
const dataset = await datasetService.createDraftDatasetFromLive(liveDataset, userID)
return _.pick(dataset, attributes);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,21 @@ const datasetStatusTransition = async (req: Request, res: Response) => {
validateRequest(req, dataset_id);

const dataset: Record<string, any> = (_.includes(liveDatasetActions, status)) ? await datasetService.getDataset(dataset_id, ["id", "status", "type", "api_version"], true) : await datasetService.getDraftDataset(dataset_id, ["id", "dataset_id", "status", "type", "api_version"])
const userID = (req as any)?.userID;
validateDataset(dataset, dataset_id, status);

switch (status) {
case "Delete":
await deleteDataset(dataset);
break;
case "ReadyToPublish":
await readyForPublish(dataset);
await readyForPublish(dataset, userID);
break;
case "Live":
await publishDataset(dataset);
await publishDataset(dataset, userID);
break;
case "Retire":
await retireDataset(dataset);
await retireDataset(dataset, userID);
break;
default:
throw obsrvError(dataset.id, "UNKNOWN_STATUS_TRANSITION", "Unknown status transition requested", "BAD_REQUEST", 400)
Expand All @@ -84,7 +85,7 @@ const deleteDataset = async (dataset: Record<string, any>) => {
}


const readyForPublish = async (dataset: Record<string, any>) => {
const readyForPublish = async (dataset: Record<string, any>, updated_by: any) => {

const draftDataset: any = await datasetService.getDraftDataset(dataset.dataset_id)
let defaultConfigs: any = _.cloneDeep(defaultDatasetConfig)
Expand All @@ -93,7 +94,14 @@ const readyForPublish = async (dataset: Record<string, any>) => {
if (draftDataset?.type === "master") {
defaultConfigs = _.omit(defaultConfigs, "dataset_config.keys_config.data_key");
}
_.mergeWith(draftDataset, defaultConfigs, draftDataset, (objValue, srcValue) => {
_.set(draftDataset, "updated_by", updated_by);
_.mergeWith(draftDataset, defaultConfigs, draftDataset, (objValue, srcValue ,key) => {
if (key === "created_by"|| key === "updated_by") {
if (objValue !== "SYSTEM") {
return objValue;
}
return srcValue;
}
if (_.isBoolean(objValue) && _.isBoolean(srcValue)) {
return objValue;
}
Expand All @@ -120,10 +128,12 @@ const readyForPublish = async (dataset: Record<string, any>) => {
*
* @param dataset
*/
const publishDataset = async (dataset: Record<string, any>) => {
const publishDataset = async (dataset: Record<string, any>, userID: any) => {

const draftDataset: Record<string, any> = await datasetService.getDraftDataset(dataset.dataset_id) as unknown as Record<string, any>

_.set(draftDataset, ["created_by"], userID);
_.set(draftDataset, ["updated_by"], userID);
console.log(draftDataset);
await validateAndUpdateDenormConfig(draftDataset);
await updateMasterDataConfig(draftDataset)
await datasetService.publishDataset(draftDataset)
Expand Down Expand Up @@ -202,10 +212,10 @@ const updateMasterDataConfig = async (draftDataset: Record<string, any>) => {
}
}

const retireDataset = async (dataset: Record<string, any>) => {
const retireDataset = async (dataset: Record<string, any>, updated_by: any) => {

await canRetireIfMasterDataset(dataset);
await datasetService.retireDataset(dataset);
await datasetService.retireDataset(dataset, updated_by);
await restartPipeline(dataset);
}

Expand Down
2 changes: 2 additions & 0 deletions api-service/src/controllers/DatasetUpdate/DatasetUpdate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ const datasetUpdate = async (req: Request, res: Response) => {
validateDataset(datasetModel, req)

const draftDataset = mergeDraftDataset(datasetModel, datasetReq);
const userID = (req as any)?.userID;
_.set(draftDataset, "updated_by", userID )
const response = await datasetService.updateDraftDataset(draftDataset);
ResponseHandler.successResponse(req, res, { status: httpStatus.OK, data: response });
}
Expand Down
10 changes: 8 additions & 2 deletions api-service/src/controllers/NotificationChannel/Notification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ const telemetryObject = { type: "notificationChannel", ver: "1.0.0" };
const createHandler = async (request: Request, response: Response, next: NextFunction) => {
try {
const payload = request.body;
const userID = (request as any)?.userID;
_.set(payload, "created_by", userID);
const notificationBody = await Notification.create(payload);
updateTelemetryAuditEvent({ request, object: { id: notificationBody?.dataValues?.id, ...telemetryObject } });
ResponseHandler.successResponse(request, response, { status: httpStatus.OK, data: { id: notificationBody.dataValues.id } })
Expand All @@ -32,6 +34,8 @@ const updateHandler = async (request: Request, response: Response, next: NextFun
if (_.get(notificationPayload, "status") === "live") {
await updateNotificationChannel(notificationPayload);
}
const userID = (request as any)?.userID;
_.set(updatedPayload, "updated_by", userID);
await Notification.update({ ...updatedPayload, status: "draft" }, { where: { id } });
ResponseHandler.successResponse(request, response, { status: httpStatus.OK, data: { id } });
} catch (err) {
Expand Down Expand Up @@ -74,7 +78,8 @@ const retireHandler = async (request: Request, response: Response, next: NextFun
if (!notificationPayload) return next({ message: httpStatus[httpStatus.NOT_FOUND], statusCode: httpStatus.NOT_FOUND });
updateTelemetryAuditEvent({ request, object: { id, ...telemetryObject }, currentRecord: notificationPayload });
await updateNotificationChannel(notificationPayload);
await Notification.update({ status: "retired" }, { where: { id } })
const userID = (request as any)?.userID;
await Notification.update({ status: "retired", updated_by: userID }, { where: { id } })
ResponseHandler.successResponse(request, response, { status: httpStatus.OK, data: { id } });
} catch (err) {
const error = createError(httpStatus.INTERNAL_SERVER_ERROR, _.get(err, "message") || httpStatus[httpStatus.INTERNAL_SERVER_ERROR])
Expand All @@ -91,7 +96,8 @@ const publishHandler = async (request: Request, response: Response, next: NextFu
if (notificationPayload.status === "live") throw new Error(httpStatus[httpStatus.CONFLICT]);
updateTelemetryAuditEvent({ request, object: { id, ...telemetryObject }, currentRecord: notificationPayload });
await publishNotificationChannel(notificationPayload);
Notification.update({ status: "live" }, { where: { id } });
const userID = (request as any)?.userID;
Notification.update({ status: "live", updated_by: userID }, { where: { id } });
ResponseHandler.successResponse(request, response, { status: httpStatus.OK, data: { id, status: "published" } });
} catch (err) {
const error = createError(httpStatus.INTERNAL_SERVER_ERROR, _.get(err, "message") || httpStatus[httpStatus.INTERNAL_SERVER_ERROR])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ export const updateQueryTemplate = async (req: Request, res: Response) => {
logger.error({ apiId, msgid, resmsgid, templateId, requestBody: req?.body, message: `Invalid template provided, A template should consist of variables ${requiredVariables} and type of json,sql`, code: "QUERY_TEMPLATE_INVALID_INPUT" })
return ResponseHandler.errorResponse({ statusCode: 400, message: `Invalid template provided, A template should consist of variables ${requiredVariables} and type of json,sql`, errCode: "BAD_REQUEST", code: "QUERY_TEMPLATE_INVALID_INPUT" }, req, res)
}

const userID = (req as any)?.userID;
requestBody.request.updated_by = userID;
await QueryTemplate.update(requestBody?.request, { where: { template_id: templateId } })
logger.info({ apiId, msgid, resmsgid, templateId, requestBody, message: `Query template updated successfully` })
ResponseHandler.successResponse(req, res, { status: 200, data: { message: "Query template updated successfully", templateId } });
Expand Down
Loading

0 comments on commit 593cae6

Please sign in to comment.