public void ProcessRequest(HttpContext context) { if (context.Session["AFWACSESSION"] == null) { throw new Exception("Must be in a legal R-AF session"); } session = context.Session["AFWACSESSION"] as AFWACsession; string mode = context.Request.Params["mode"]; // mode=dumpraf // mode=compare string requestorUserEID = context.Request.Params["usereid"]; string requestorUserName = context.Request.Params["username"]; string pathInput = context.Request.Params["pathinput"]; bool boolReportInternalIdmRoles = false; bool boolSaveToHistory = bool.Parse(context.Request.Params["save"]); bool boolDoCompare = (mode == "compare"); bool boolCaseSens = false; string CSVlistOfInterestingRoles = "-3"; string CSVlistOfInterestingSubprocesses = "-3"; // // New format for the CSVlist: // Still comma-separated. // But now each item is either: // an integer // "SP/###" where ### is the ID number for a subprocess // Our goal is to split this into two CSV lists: // list of interesting roles // list of interesting subprocesses (meaning all its roles are interesting) // So here we must tokenize the incoming role list. StringTok.StringTokenizer TK = new StringTok.StringTokenizer(context.Request.Params["roles"], ","); string curnode; while (TK.HasMoreTokens()) { curnode = TK.NextToken(); if (curnode.StartsWith("SP/")) { curnode = curnode.Substring(3); CSVlistOfInterestingSubprocesses += ("," + curnode); } else { CSVlistOfInterestingRoles += ("," + curnode); } } int errcountEntitlements = 0; int errcountRoleMetadata = 0; DataTable dt_dumpFromSAP = null; if (boolDoCompare) { string pathTempFolder = Path.GetDirectoryName(pathInput); string pathTempFile = Path.GetFileName(pathInput); // Load the CSV file that shows the world as SAP claims it should be. dt_dumpFromSAP = HELPERS.LoadCsv(pathTempFolder, System.IO.Path.GetFileName(pathTempFile)); } OdbcCommand cmd = new OdbcCommand(); cmd.Connection = HELPERS.NewOdbcConn(); Workbook book = null; WorksheetRow row; Worksheet sheetMetadata = null; Worksheet sheetDeltas = null; if (boolSaveToHistory) { ENGINEreport = new IReconcReport(HELPERS.NewOdbcConn()); IDreport = ENGINEreport.NewReconcReport(DateTime.Now, session.idUser); ENGINEreport.SetReconcReport (IDreport, DateTime.Now, "Comparison via upload of file " + pathInput, session.idUser, "SAP"); ENGINEreportDiffItem = new IReconcDiffItem(HELPERS.NewOdbcConn()); } else if (boolDoCompare) { book = new Workbook(); context.Response.ContentType = "text/xml"; context.Response.AddHeader("Content-Disposition", "filename=RAFsapReconcile.xls;attachment"); sheetMetadata = book.Worksheets.Add("Metadata"); row = sheetMetadata.Table.Rows.Add(); row.Cells.Add("Run Date:"); row.Cells.Add(DateTime.Now.ToUniversalTime().ToLongDateString() + " UTC"); row = sheetMetadata.Table.Rows.Add(); row.Cells.Add("Run Time:"); row.Cells.Add(DateTime.Now.ToUniversalTime().ToLongTimeString() + " UTC"); // row = sheetMetadata.Table.Rows.Add(); // row.Cells.Add("User EID:"); // row.Cells.Add(requestorUserEID); row = sheetMetadata.Table.Rows.Add(); row.Cells.Add("User Name:"); row.Cells.Add(requestorUserName); row = sheetMetadata.Table.Rows.Add(); row = sheetMetadata.Table.Rows.Add(); row.Cells.Add("STATISTICS"); sheetDeltas = book.Worksheets.Add("Reconciliation"); row = RecordDelta(sheetDeltas, "Role Name", "Platform", "Difference", "Action", "Difference Type", ""); } else { // This is for mode==dumpraf (export entitlements only) context.Response.ContentType = "text/csv"; context.Response.AddHeader("Content-Disposition", "filename=RAF_SAPexport.csv;attachment"); } string extraconds = " AND ((TEASS.c_u_EditStatus & 4)<>4) "; // Perform a massive SQL select to obtain all active TCODE entitlements in R-AF string SQL = @" SELECT TENT.c_id as EntID, BROL.c_u_Name as SAProlename, RTRIM(LTRIM(BROL.c_u_Description)) as SAProleDescription, BROL.c_u_Platform as platform, UPPER(TENT.c_u_TCode) as tcode, BROL.c_u_System as sapsystem, SUBPR.c_u_Name as subprname FROM t_RBSR_AUFW_u_TcodeAssignment TEASS LEFT OUTER JOIN t_RBSR_AUFW_u_TcodeEntitlement TENT ON TEASS.c_r_TcodeEntitlement = TENT.c_id LEFT OUTER JOIN t_RBSR_AUFW_u_SAProle BROL ON BROL.c_id = TEASS.c_r_SAPRole LEFT OUTER JOIN t_RBSR_AUFW_u_TcodeAssignmentSet TEASET ON TEASET.c_id = TEASS.c_r_TcodeAssignmentSet LEFT OUTER JOIN t_RBSR_AUFW_u_SubProcess SUBPR ON TEASET.c_r_SubProcess = SUBPR.c_id WHERE (TEASET.c_u_Status = 'ACTIVE') AND (SUBPR.c_r_Process NOT IN (7)) AND ( (BROL.c_id IN (" + CSVlistOfInterestingRoles + ")) OR " + "(BROL.c_r_SubProcess IN (" + CSVlistOfInterestingSubprocesses + ")) ) " + extraconds + " ORDER BY TEASS.c_r_SAProle;"; cmd.CommandText = SQL; OdbcDataReader dr = cmd.ExecuteReader(); // Key: SAProlename + '\001' + platform + "\001" + tcodeautomappedtoUPPERCASE // Value: code meaning: // 1 means active in RAF but not (yet) seen in incoming data from SAP // This is really the only value ever seen. // If one of these is seen in the incoming data, this item is removed from the dict. Dictionary <string, int> DICTactiveRoleplatToTcode = new Dictionary <string, int>(); string keyDelimiter = "|=|"; // These map role names to role descriptions //Dictionary<string, string> DICTactiveBroles = new Dictionary<string, string>(); //Dictionary<string, string> DICTidmBroles = new Dictionary<string, string>(); while (dr.Read()) { int IDwsentrow = (int)(dr.GetValue(0)); string brolename = dr.GetValue(1).ToString(); string bdescr = dr.GetValue(2).ToString(); string platform = dr.GetValue(3).ToString(); string tcode = dr.GetValue(4).ToString().ToUpper(); string sapsystem = dr.GetValue(5).ToString(); string subpr = dr.GetValue(6).ToString(); string key = brolename + keyDelimiter + platform + keyDelimiter + tcode; if (!boolDoCompare) { context.Response.Write(CSVquoteize(brolename)); context.Response.Write(","); context.Response.Write(CSVquoteize(sapsystem)); context.Response.Write(","); context.Response.Write(CSVquoteize(platform)); context.Response.Write(","); context.Response.Write(CSVquoteize(tcode)); context.Response.Write(","); context.Response.Write(CSVquoteize(subpr)); context.Response.Write("\n"); } else { if (!DICTactiveRoleplatToTcode.ContainsKey(key)) { DICTactiveRoleplatToTcode.Add(key, 1); } } } // We have completed the reading of the output from the SELECT. // Now comes the comparison. if (boolDoCompare) { Queue <string> QUEUE_idmRowsLackingActiveMatch = new Queue <string>(); foreach (DataRow idmrow in dt_dumpFromSAP.Rows) { string idmrsrcRolename = idmrow[0].ToString().Trim(); string idmrsrcPlatform = idmrow[1].ToString().Trim(); string idmrsrcValue = idmrow[2].ToString().Trim(); string idmrsrcObjtype = idmrow[3].ToString().Trim().ToLower(); switch (idmrsrcObjtype) { case "tcode": idmrsrcValue = idmrsrcValue.ToUpper(); break; default: throw new Exception("Only TCode data is currently supported in the incoming data from SAP"); } string idmrsrcPrivForCompare = idmrsrcRolename + keyDelimiter + idmrsrcPlatform + keyDelimiter + idmrsrcValue; if (DICTactiveRoleplatToTcode.ContainsKey(idmrsrcPrivForCompare)) { DICTactiveRoleplatToTcode.Remove(idmrsrcPrivForCompare); } else { RecordDelta (sheetDeltas, idmrsrcRolename, idmrsrcPlatform, idmrsrcValue, "Remove", "tcode", null); errcountEntitlements++; } } // Now we are looking for info that was in RAF but unmatched in the incoming. // These turn into "ADD" instructions. foreach (string keytoadd in DICTactiveRoleplatToTcode.Keys) { StringTok.StringTokenizer TK2 = new StringTok.StringTokenizer(keytoadd, keyDelimiter); string reportRolename = TK2.NextToken(); string reportPlatform = TK2.NextToken(); string reportTcode = TK2.NextToken(); RecordDelta(sheetDeltas, reportRolename, reportPlatform, reportTcode, "Add", "tcode", null); errcountEntitlements++; } if (book != null) { row = sheetMetadata.Table.Rows.Add(); row.Cells.Add(" - Tcode deltas:"); row.Cells.Add(errcountEntitlements.ToString()); book.Save(context.Response.OutputStream); } else { context.Response.Redirect("../Page_Reconc_History.aspx"); } } }
public void ProcessRequest(HttpContext context) { if (context.Session["AFWACSESSION"] == null) { throw new Exception("Must be in a legal R-AF session"); } session = context.Session["AFWACSESSION"] as AFWACsession; string mode = context.Request.Params["mode"]; // mode=dumpraf // mode=compare string requestorUserEID = context.Request.Params["usereid"]; string requestorUserName = context.Request.Params["username"]; string pathIdmInput = context.Request.Params["pathidminput"]; bool boolReportInternalIdmRoles = bool.Parse(context.Request.Params["showinternal"]); bool boolSaveToHistory = bool.Parse(context.Request.Params["save"]); bool boolDoCompare = (mode == "compare"); bool boolCaseSens = false; string CSVlistOfInterestingRoles = "-3"; string CSVlistOfInterestingSubprocesses = "-3"; // // New format for the CSVlist: // Still comma-separated. // But now each item is either: // an integer // "SP/###" where ### is the ID number for a subprocess // Our goal is to split this into two CSV lists: // list of interesting roles // list of interesting subprocesses (meaning all its roles are interesting) // So here we must tokenize the incoming role list. StringTok.StringTokenizer TK = new StringTok.StringTokenizer(context.Request.Params["roles"], ","); string curnode; while (TK.HasMoreTokens()) { curnode = TK.NextToken(); if (curnode.StartsWith("SP/")) { curnode = curnode.Substring(3); CSVlistOfInterestingSubprocesses += ("," + curnode); } else { CSVlistOfInterestingRoles += ("," + curnode); } } int errcountEntitlements = 0; int errcountRoleMetadata = 0; DataTable dt_idmdump = null; if (boolDoCompare) { string pathTempFolder = Path.GetDirectoryName(pathIdmInput); string pathTempFile = Path.GetFileName(pathIdmInput); // Load the IDM-dump CSV file. // Load the IDM-dump CSV file. // Load the IDM-dump CSV file. // Load the IDM-dump CSV file. // Load the IDM-dump CSV file. dt_idmdump = HELPERS.LoadCsv(pathTempFolder, System.IO.Path.GetFileName(pathTempFile)); } OdbcCommand cmd = new OdbcCommand(); cmd.Connection = HELPERS.NewOdbcConn(); Workbook book = null; WorksheetRow row; Worksheet sheetMetadata = null; Worksheet sheetDeltas = null; Worksheet sheetErrors = null; if (boolSaveToHistory) { ENGINEreport = new IReconcReport(HELPERS.NewOdbcConn()); IDreport = ENGINEreport.NewReconcReport(DateTime.Now, session.idUser); ENGINEreport.SetReconcReport (IDreport, DateTime.Now, "Comparison via upload of file " + pathIdmInput, session.idUser, "IDM"); ENGINEreportDiffItem = new IReconcDiffItem(HELPERS.NewOdbcConn()); } else { book = new Workbook(); context.Response.ContentType = "application/vnd.xls"; context.Response.AddHeader("Content-Disposition", "filename=RAFidmReconcile.xls;attachment"); sheetMetadata = book.Worksheets.Add("Metadata"); sheetErrors = book.Worksheets.Add("Errors"); row = sheetMetadata.Table.Rows.Add(); row.Cells.Add("Run Date:"); row.Cells.Add(DateTime.Now.ToUniversalTime().ToLongDateString() + " UTC"); row = sheetMetadata.Table.Rows.Add(); row.Cells.Add("Run Time:"); row.Cells.Add(DateTime.Now.ToUniversalTime().ToLongTimeString() + " UTC"); // row = sheetMetadata.Table.Rows.Add(); // row.Cells.Add("User EID:"); // row.Cells.Add(requestorUserEID); row = sheetMetadata.Table.Rows.Add(); row.Cells.Add("User Name:"); row.Cells.Add(requestorUserName); row = sheetMetadata.Table.Rows.Add(); row.Cells.Add("Include list of IDM ELE_INT_ and INT_ roles"); row.Cells.Add(boolReportInternalIdmRoles.ToString()); row = sheetMetadata.Table.Rows.Add(); row = sheetMetadata.Table.Rows.Add(); row.Cells.Add("STATISTICS"); sheetDeltas = book.Worksheets.Add("Reconciliation"); row = RecordDelta(sheetDeltas, "Role Name", "Difference", "Action", "Difference Type", ""); } OdbcConnection conn2 = HELPERS.NewOdbcConn_FORCE(); IEntitlement ENGINEwsent = new IEntitlement(conn2); string SQLsubpr = @" SELECT c_r_SubProcess, c_u_Name FROM t_RBSR_AUFW_u_BusRole;"; cmd.CommandText = SQLsubpr; OdbcDataReader drSubpr = cmd.ExecuteReader(); Dictionary <string, string> MAPbrolenamesToSubprids = new Dictionary <string, string>(); while (drSubpr.Read()) { int IDsubprid = (int)(drSubpr.GetValue(0)); string brolename = drSubpr.GetValue(1).ToString(); if (!MAPbrolenamesToSubprids.ContainsKey(brolename)) { MAPbrolenamesToSubprids.Add(brolename, IDsubprid.ToString()); // + " = " + STRsubpr); } } drSubpr.Close(); string extraconds = " AND (TEASS.c_u_Status NOT IN ('X')) "; // Perform a massive SQL select to obtain all active entitlements in R-AF string SQL = @" SELECT TENT.c_id as EntID, BROL.c_u_Name as BusRole, RTRIM(LTRIM(BROL.c_u_Description)) as BusRoleDescr, MVF.c_u_Formula as Formula, MVF.c_u_KEYapplication as Appl, OWNERS.c_u_EID as EIDprimaryApprover, SUBPR.c_u_Name as SubprocessName, BROL.c_r_SubProcess as SubprocessID FROM t_RBSR_AUFW_u_EntAssignment TEASS LEFT OUTER JOIN t_RBSR_AUFW_u_Entitlement TENT ON TEASS.c_r_Entitlement = TENT.c_id LEFT OUTER JOIN t_RBSR_AUFW_u_BusRole BROL ON BROL.c_id = TEASS.c_r_BusRole LEFT OUTER JOIN t_RBSR_AUFW_u_MVFormula MVF ON MVF.c_u_KEYapplication = TENT.c_u_Application LEFT OUTER JOIN t_RBSR_AUFW_u_EntAssignmentSet TEASET ON TEASET.c_id = TEASS.c_r_EntAssignmentSet LEFT OUTER JOIN t_RBSR_AUFW_u_SubProcess SUBPR ON TEASET.c_r_SubProcess = SUBPR.c_id LEFT OUTER JOIN t_RBSR_AUFW_u_BusRoleOwner OWNERS ON ( (OWNERS.c_r_BusRole = BROL.c_id) AND (OWNERS.c_u_Rank='appr') ) WHERE (TEASET.c_u_Status = 'ACTIVE') AND (SUBPR.c_r_Process NOT IN (7)) AND ( (BROL.c_id IN (" + CSVlistOfInterestingRoles + ")) OR " + "(BROL.c_r_SubProcess IN (" + CSVlistOfInterestingSubprocesses + ")) ) " + extraconds + " ORDER BY TEASS.c_r_BusRole;"; cmd.CommandText = SQL; OdbcDataReader dr = cmd.ExecuteReader(); Dictionary <string, string> DICTactiveEnts = new Dictionary <string, string>(); // These map role names to role descriptions Dictionary <string, string> DICTactiveBroles = new Dictionary <string, string>(); Dictionary <string, string> DICTidmBroles = new Dictionary <string, string>(); // Key = rolename + EID of primary approver // Value = 1 Dictionary <string, string> DICTroleApprover = new Dictionary <string, string>(); Queue <string> QUEUEmsgsWarning = new Queue <string>(); // WE ARE NOW READING THE DATA COMING FROM R-AF VIA SQL QUERY // WE ARE NOW READING THE DATA COMING FROM R-AF VIA SQL QUERY // WE ARE NOW READING THE DATA COMING FROM R-AF VIA SQL QUERY // WE ARE NOW READING THE DATA COMING FROM R-AF VIA SQL QUERY // WE ARE NOW READING THE DATA COMING FROM R-AF VIA SQL QUERY while (dr.Read()) { int IDwsentrow = (int)(dr.GetValue(0)); string brolename = dr.GetValue(1).ToString(); string broledescr = dr.GetValue(2).ToString(); string STRformula = dr.GetValue(3).ToString(); string STRapp = dr.GetValue(4).ToString(); string STRapproverEID = dr.GetValue(5).ToString(); string STRsubpr = dr.GetValue(6).ToString(); int IDsubpr = (int)(dr.GetValue(7)); if (!DICTactiveBroles.ContainsKey(brolename)) { DICTactiveBroles.Add(brolename, broledescr); } /* * if (!MAPbrolenamesToSubprids.ContainsKey(brolename)) * { * MAPbrolenamesToSubprids.Add(brolename, IDsubpr.ToString() + " = " + STRsubpr); * } */ if (STRapproverEID.Length > 1) { try { DICTroleApprover.Add( brolename + (char)1 + STRapproverEID, "1"); } catch (Exception) { } } returnGetEntitlement OBJwsent = ENGINEwsent.GetEntitlement(IDwsentrow); // SKLAR NOTE: the returnGetEntitlement struct has every column/field already segregated int repaircount = 0; TurnNullsToEmptyStrings(ref OBJwsent, ref repaircount); if (STRformula == "") { STRformula = "\"TBD - " + dr.GetValue(4).ToString() + "\""; } else { STRformula = HttpUtility.HtmlDecode(STRformula.Trim()); } // We have the formula; now we can evaluate. Evaluator ev = new Evaluator(Eval3.eParserSyntax.cSharp, false); ev.AddEnvironmentFunctions(this); ev.AddEnvironmentFunctions(new ManifestFormulaEvaluatorFunctions(OBJwsent)); opCode lCode; try { lCode = ev.Parse(STRformula); } catch (Exception e) { if (book != null) { sheetMetadata.Table.Rows.Add().Cells.Add("The formula [[" + STRformula + "]] for this app [[" + STRapp + "]] has parse errors: " + e.ToString()); } else { context.Response.Write("The formula [[" + STRformula + "]] for this app [[" + STRapp + "]] has parse errors: " + e.ToString()); } continue; } string RESLT; try { RESLT = lCode.value.ToString(); } catch (Exception e) { RESLT = "NULL"; //context.Response.Write("Interpreting the formula for this app resulted in errors: " + e.ToString()); //return; } string RESLTforCompare = RESLT; if (!boolCaseSens) { RESLTforCompare = RESLT.ToLower().Replace(" ", ""); } if (!boolDoCompare) { context.Response.Write(CSVquoteize(brolename)); context.Response.Write(","); context.Response.Write(CSVquoteize(broledescr)); context.Response.Write(","); context.Response.Write(CSVquoteize(RESLTforCompare)); context.Response.Write("\n"); } else { // Enter the role name and the privilegestring into a dictionary try { DICTactiveEnts.Add(brolename + (char)1 + RESLTforCompare, RESLT); } catch (Exception eduringprivadd) { // This situation occurs when two or more distinct entitlements in RAF // generate the very same priv string (because they differ in a field that // "does not count" towards generation of the priv string. QUEUEmsgsWarning.Enqueue ("Role " + brolename + ": privilege was registered redundantly: " + RESLTforCompare); } } } // Now comes the comparison. if (boolDoCompare) { Queue <string> QUEUE_idmRowsLackingActiveMatch = new Queue <string>(); // HERE WE ARE ACTUALLY LOOKING AT THE DATA COMING IN FROM THE IDM DUMP FILE // HERE WE ARE ACTUALLY LOOKING AT THE DATA COMING IN FROM THE IDM DUMP FILE // HERE WE ARE ACTUALLY LOOKING AT THE DATA COMING IN FROM THE IDM DUMP FILE // HERE WE ARE ACTUALLY LOOKING AT THE DATA COMING IN FROM THE IDM DUMP FILE // HERE WE ARE ACTUALLY LOOKING AT THE DATA COMING IN FROM THE IDM DUMP FILE // HERE WE ARE ACTUALLY LOOKING AT THE DATA COMING IN FROM THE IDM DUMP FILE // HERE WE ARE ACTUALLY LOOKING AT THE DATA COMING IN FROM THE IDM DUMP FILE // HERE WE ARE ACTUALLY LOOKING AT THE DATA COMING IN FROM THE IDM DUMP FILE foreach (DataRow idmrow in dt_idmdump.Rows) { string idmrsrcRolename = idmrow[0].ToString().Trim(); string idmrsrcValue = idmrow[1].ToString().Trim(); string idmrsrcObjType = idmrow[2].ToString().Trim(); switch (idmrsrcObjType) { case "PrimaryApprover": case "RoleApprover": string target = idmrsrcRolename + (char)1 + idmrsrcValue; if (DICTroleApprover.ContainsKey(target)) { // Was also found in RAF, so nothing to report. DICTroleApprover.Remove(target); } else { // Was not found in RAF, so report a need for removal RecordDelta(sheetDeltas, idmrsrcRolename, idmrsrcValue, "Remove", "PrimaryApprover", null); } break; case "RoleDescription": if (!DICTidmBroles.ContainsKey(idmrsrcRolename)) { DICTidmBroles.Add(idmrsrcRolename, idmrsrcValue); } break; case "Entitlement": string idmrsrcPrivForCompare = idmrsrcValue; if (!boolCaseSens) { idmrsrcPrivForCompare = idmrsrcValue.ToLower().Replace(" ", ""); } string idmrsrcKey = idmrsrcRolename + (char)1 + idmrsrcPrivForCompare; if (DICTactiveEnts.ContainsKey(idmrsrcKey)) { DICTactiveEnts.Remove(idmrsrcKey); } else { QUEUE_idmRowsLackingActiveMatch.Enqueue(idmrsrcKey); /* * int idxSep = idmrsrcKey.IndexOf((char)1); * string reportRolename = idmrsrcKey.Substring(0,idxSep); * string reportPriv = idmrsrcKey.Substring(idxSep+1); * */ if (!boolReportInternalIdmRoles) { if (idmrsrcRolename.StartsWith("ELE_INT_") || idmrsrcRolename.StartsWith("INT_")) { continue; } } try { RecordDelta(sheetDeltas, idmrsrcRolename, idmrsrcValue, "Remove", "Entitlement", MAPbrolenamesToSubprids[idmrsrcRolename]); } catch (Exception) { RecordDelta(sheetDeltas, idmrsrcRolename, idmrsrcValue, "Remove", "Entitlement", "Note: this role is not known to the RAF system at all."); } errcountEntitlements++; } break; } } foreach (string keytoadd in DICTactiveEnts.Keys) { int idxSep = keytoadd.IndexOf((char)1); string reportRolename = keytoadd.Substring(0, idxSep); string reportPriv = DICTactiveEnts[keytoadd]; if (!boolReportInternalIdmRoles) { if (reportRolename.StartsWith("ELE_INT_") || reportRolename.StartsWith("INT_")) { continue; } } RecordDelta(sheetDeltas, reportRolename, reportPriv, "Add", "Entitlement", null); errcountEntitlements++; } foreach (string keytoadd in DICTroleApprover.Keys) { int idxSep = keytoadd.IndexOf((char)1); string reportRolename = keytoadd.Substring(0, idxSep); string reportEID = keytoadd.Substring(idxSep + 1); if (!boolReportInternalIdmRoles) { if (reportRolename.StartsWith("ELE_INT_") || reportRolename.StartsWith("INT_")) { continue; } } RecordDelta(sheetDeltas, reportRolename, reportEID, "Add", "PrimaryApprover", null); } // Roles as a whole foreach (string rolePresentInRAF in DICTactiveBroles.Keys) { if (DICTidmBroles.ContainsKey(rolePresentInRAF)) { // This role is present in both RAF and IDM. // But perhaps differs in description? if (DICTactiveBroles[rolePresentInRAF] != DICTidmBroles[rolePresentInRAF]) { // 1. Do a remove RecordDelta(sheetDeltas, rolePresentInRAF, DICTidmBroles[rolePresentInRAF], "Remove", "RoleDescription", ""); // 2. Do an add RecordDelta(sheetDeltas, rolePresentInRAF, DICTactiveBroles[rolePresentInRAF], "Add", "RoleDescription", ""); errcountRoleMetadata++; } //Record having seen this. DICTidmBroles.Remove(rolePresentInRAF); } else { RecordDelta(sheetDeltas, rolePresentInRAF, DICTactiveBroles[rolePresentInRAF], "Add", "Role", null); errcountRoleMetadata++; } } foreach (string rolePresentInIDM in DICTidmBroles.Keys) { if (!boolReportInternalIdmRoles) { if (rolePresentInIDM.StartsWith("ELE_INT_") || rolePresentInIDM.StartsWith("INT_")) { continue; } } RecordDelta(sheetDeltas, rolePresentInIDM, rolePresentInIDM, "Remove", "Role", null); errcountRoleMetadata++; } if (book != null) { row = sheetMetadata.Table.Rows.Add(); row.Cells.Add(" - Entitlement deltas:"); row.Cells.Add(errcountEntitlements.ToString()); row = sheetMetadata.Table.Rows.Add(); row.Cells.Add(" - Role deltas:"); row.Cells.Add(errcountRoleMetadata.ToString()); if (QUEUEmsgsWarning.Count > 0) { row = sheetMetadata.Table.Rows.Add(); row.Cells.Add(" - Warning messages regarding RAF-side data:"); while (QUEUEmsgsWarning.Count > 0) { string msg = QUEUEmsgsWarning.Dequeue(); row = sheetMetadata.Table.Rows.Add(); row.Cells.Add(""); row.Cells.Add(msg); } } book.Save(context.Response.OutputStream); } else { context.Response.Redirect("../Page_Reconc_History.aspx"); } } }