Different users triggering change risk assessments without completing them get security error Script: [assessment_take2]: Unauthorized assessment takerDescriptionDifferent users triggering change risk assessments without completing them get security error, due to reuse of assessment instance that is ready to take between users when each should have their own assessment instance. These assessment instances are associated to a user and this session user is checked against the user that created the assessment instance and does not match. Error logs show contains:*** ERROR *** *** Script: [assessment_take2]: Unauthorized assessment takerSteps to Reproduce 1. Install change risk assessment plugin2. As a change manager user create a normal change request.3. Click Risk Assessment, but do not submit or close it. Reload the page and check there is a "ready to take" assessment associated to the change request4. As an Itil user go to the Change request created in #2 and click Risk Assessment.5. Complete the risk assessment. Expected: Risk Assessment modal dialog closes and risk is set accordingly Actual:Risk Assessment modal dialog does not close, and redirects to another page in the dialog.Also Error logs show contains: *** ERROR *** *** Script: [assessment_take2]: Unauthorized assessment taker RhinoExceptions Couldn't decipher the stack trace resulting from the following JavaScriptException:RhinoExceptions *** ERROR *** java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committedorg.mozilla.javascript.JavaScriptException: java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committedWorkaroundModify script include: ChangeRiskAsmt adding following function/method: invokeAssessment: function(data) { var asmt = { "hasAsmt": false, "asmtComplete": false }; if (!data) return asmt; var userSysId = data.userId || gs.getUserID(); var changeRequestSysId = data.sysId || ""; var tableName = data.tableName || ""; var changeRiskAsmtSysId = data.riskAsmtSysId || ""; var copyAsmt = false; if (data && data.copyAsmt) copyAsmt = data.copyAsmt + "" === "true"; var changeRiskAsmtSysIds; var changeGr = new GlideRecordSecure(tableName); if (!changeGr.get(changeRequestSysId) || !changeGr.canWrite()) return asmt; if (!changeRiskAsmtSysId && (changeRequestSysId && tableName)) { changeRiskAsmtSysIds = this._getChangeRiskAsmtsByConditions(changeRequestSysId, tableName); // Get first Change Risk Assessment but in future handle all if (changeRiskAsmtSysIds.length > 0) changeRiskAsmtSysId = changeRiskAsmtSysIds[0]; } if (!userSysId || !changeRequestSysId || !changeRiskAsmtSysId) return asmt; if (this._log.atLevel(global.GSLog.DEBUG)) this._log.debug("[invokeAssessment] userSysId: " + userSysId + " changeRequestSysId: " + changeRequestSysId + " changeRiskAsmtSysId: " + changeRiskAsmtSysId); // Remove Cancelled assessments so they can be re-taken var cancelledAsmtInstanceSysIds = this._getAsmtInstancesByTaskId(changeRequestSysId, this.CANCELLED, changeRiskAsmtSysIds); if (cancelledAsmtInstanceSysIds.length > 0) this.deleteAsmtInstance(cancelledAsmtInstanceSysIds[0]); var asmtInstanceSysId = ""; var incompleteAsmtInstanceSysIds = this._getAsmtInstancesByTaskId(changeRequestSysId, this.INCOMPLETE, changeRiskAsmtSysIds, gs.getUserID()); if (incompleteAsmtInstanceSysIds.length > 0) asmtInstanceSysId = incompleteAsmtInstanceSysIds[0]; else { var completeAsmtInstanceSysIds = this._getAsmtInstancesByTaskId(changeRequestSysId, this.COMPLETE, changeRiskAsmtSysIds); if (completeAsmtInstanceSysIds.length > 0 && !copyAsmt) asmt.asmtComplete = true; else { var previousAsmtInstanceSysId = ""; if (completeAsmtInstanceSysIds.length > 0) previousAsmtInstanceSysId = completeAsmtInstanceSysIds[0]; asmtInstanceSysId = this._createAsmt(changeRiskAsmtSysId, changeRequestSysId, userSysId); if (copyAsmt && previousAsmtInstanceSysId) this._copyAsmt(previousAsmtInstanceSysId, asmtInstanceSysId); } } asmt.hasAsmt = true; asmt.changeRequestSysId = changeRequestSysId; asmt.asmtInstanceSysId = asmtInstanceSysId; asmt.changeRiskAsmtSysId = changeRiskAsmtSysId; asmt.riskAsmtName = this._getAssessmentName(changeRiskAsmtSysId) || ""; if (this._log.atLevel(global.GSLog.DEBUG)) this._log.debug("[invokeAssessment] asmt: " + JSON.stringify(asmt)); return asmt; }, _getAsmtInstancesByTaskId: function(taskId, state, matchingAsmtSysIds, userSysId) { state = this._isAsmtComplete(state) ? this.COMPLETE : this._getAsmtState(state); if (this._log.atLevel(global.GSLog.DEBUG)) this._log.debug("[_getAsmtInstancesByTaskId] taskId: " + taskId + " state: " + state); if (!taskId) return []; var asmtInstances = []; var gr = new GlideRecord(this.ASMT_INSTANCE); gr.addQuery("task_id", taskId); if (Array.isArray(matchingAsmtSysIds)) gr.addQuery("metric_type", "IN", matchingAsmtSysIds); if (state === this.COMPLETE) gr.addQuery("state", this.COMPLETE); else gr.addQuery("state", this.NOT, this.COMPLETE); // incomplete or cancelled if (userSysId) gr.addQuery("user", userSysId); gr.addQuery("metric_type.sys_class_name", this.CHANGE_RISK_ASMT); gr.orderByDesc("sys_created_on"); gr.query(); if (this._log.atLevel(global.GSLog.DEBUG)) this._log.debug("[_getAsmtInstancesByTaskId] encodedQuery: " + gr.getEncodedQuery()); while (gr.next()) asmtInstances.push(gr.getUniqueValue()); if (this._log.atLevel(global.GSLog.DEBUG)) this._log.debug("[_getAsmtInstancesByTaskId] " + state + " assessment instances: " + asmtInstances.length + "" + JSON.stringify(asmtInstances)); return asmtInstances; },Related Problem: PRB1983792