/// <summary> /// Load the internal database in memory from the XML file of all NIST controls. /// </summary> /// <param name="context">The database in memory</param> /// <returns></returns> public static void LoadControlsXML(ControlsDBContext context) { List <Control> controls = LoadControls(); // for each one, load into the in-memory DB ControlSet cs; string formatNumber; // setup the database record to store foreach (Control c in controls) { cs = new ControlSet(); // the flattened controls table listing for the in memory DB cs.family = c.family; cs.number = c.number; cs.priority = c.priority; cs.title = c.title; if (!string.IsNullOrEmpty(c.supplementalGuidance)) { cs.supplementalGuidance = c.supplementalGuidance.Replace("\\r", "").Replace("\\n", ""); } if (c.childControls.Count > 0) { foreach (ChildControl cc in c.childControls) { cs.id = Guid.NewGuid(); // need a new PK ID for each record saved if (!string.IsNullOrEmpty(cc.description)) { cs.subControlDescription = cc.description.Replace("\r", "").Replace("\n", ""); } formatNumber = cc.number.Replace(" ", ""); // remove periods and empty space for searching later if (formatNumber.EndsWith(".")) { formatNumber = formatNumber.Substring(0, formatNumber.Length - 1); // take off the trailing period } cs.subControlNumber = formatNumber; cs.highimpact = cc.highimpact; cs.moderateimpact = cc.moderateimpact; cs.lowimpact = cc.lowimpact; context.ControlSets.Add(cs); // for each sub control, do a save on the whole thing Console.WriteLine("Adding number " + cs.subControlNumber); context.SaveChanges(); } } else { cs.id = Guid.NewGuid(); cs.highimpact = c.highimpact; cs.moderateimpact = c.moderateimpact; cs.lowimpact = c.lowimpact; context.ControlSets.Add(cs); // for some reason no sub controls context.SaveChanges(); } } context.SaveChanges(); }
static void Main(string[] args) { LogManager.Configuration = new XmlLoggingConfiguration($"{AppContext.BaseDirectory}nlog.config"); var logger = LogManager.GetLogger("openrmf_msg_controls"); ControlsDBContext _context; // Create a new connection factory to create a connection. ConnectionFactory cf = new ConnectionFactory(); // add the options for the server, reconnecting, and the handler events Options opts = ConnectionFactory.GetDefaultOptions(); opts.MaxReconnect = -1; opts.ReconnectWait = 2000; opts.Name = "openrmf-msg-controls"; opts.Url = Environment.GetEnvironmentVariable("NATSSERVERURL"); opts.AsyncErrorEventHandler += (sender, events) => { logger.Info("NATS client error. Server: {0}. Message: {1}. Subject: {2}", events.Conn.ConnectedUrl, events.Error, events.Subscription.Subject); }; opts.ServerDiscoveredEventHandler += (sender, events) => { logger.Info("A new server has joined the cluster: {0}", events.Conn.DiscoveredServers); }; opts.ClosedEventHandler += (sender, events) => { logger.Info("Connection Closed: {0}", events.Conn.ConnectedUrl); }; opts.ReconnectedEventHandler += (sender, events) => { logger.Info("Connection Reconnected: {0}", events.Conn.ConnectedUrl); }; opts.DisconnectedEventHandler += (sender, events) => { logger.Info("Connection Disconnected: {0}", events.Conn.ConnectedUrl); }; // Creates a live connection to the NATS Server with the above options IConnection c = cf.CreateConnection(opts); var options = new DbContextOptionsBuilder <ControlsDBContext>().UseInMemoryDatabase("ControlSet").Options; _context = new ControlsDBContext(options); // setup the internal database ControlsLoader.LoadControlsXML(_context); // send back a full listing of controls based on the filter passed in EventHandler <MsgHandlerEventArgs> getControls = (sender, natsargs) => { try { // print the message logger.Info("New NATS subject: {0}", natsargs.Message.Subject); logger.Info("New NATS data: {0}", Encoding.UTF8.GetString(natsargs.Message.Data)); var listing = _context.ControlSets.ToList(); var result = new List <ControlSet>(); // put all results in here Filter filter = JsonConvert.DeserializeObject <Filter>(Encoding.UTF8.GetString(natsargs.Message.Data)); if (listing != null) { // figure out the impact level filter if (filter != null && !string.IsNullOrEmpty(filter.impactLevel) && filter.impactLevel.Trim().ToLower() == "low") { result = listing.Where(x => x.lowimpact).ToList(); } else if (filter != null && !string.IsNullOrEmpty(filter.impactLevel) && filter.impactLevel.Trim().ToLower() == "moderate") { result = listing.Where(x => x.moderateimpact).ToList(); } else if (filter != null && !string.IsNullOrEmpty(filter.impactLevel) && filter.impactLevel.Trim().ToLower() == "high") { result = listing.Where(x => x.highimpact).ToList(); } else { result = listing; // get all the data } // include things that are not P0 meaning not used, and that there is no low/moderate/high designation // these should always be included where the combination of all "false" and not P0 = include them result.AddRange(listing.Where(x => x.priority != "P0" && x.family.ToLower() != "pii" && !x.lowimpact && !x.moderateimpact && !x.highimpact).ToList()); // see if the PII filter is true, and if so add in the PII family by appending that to the result from above if (filter.pii) { result.AddRange(listing.Where(x => !string.IsNullOrEmpty(x.family) && x.family.ToLower() == "pii").ToList()); } } // now publish it back out w/ the reply subject string msg = JsonConvert.SerializeObject(result); // publish back out on the reply line to the calling publisher logger.Info("Sending back compressed Checklist Data"); c.Publish(natsargs.Message.Reply, Encoding.UTF8.GetBytes(Compression.CompressString(msg))); c.Flush(); // flush the line } catch (Exception ex) { // log it here logger.Error(ex, "Error retrieving controls for the filter sent {0}", Encoding.UTF8.GetString(natsargs.Message.Data)); } }; // send back a full listing of controls based on the filter passed in EventHandler <MsgHandlerEventArgs> getControlsByTerm = (sender, natsargs) => { try { // print the message logger.Info("New NATS subject: {0}", natsargs.Message.Subject); logger.Info("New NATS data: {0}", Encoding.UTF8.GetString(natsargs.Message.Data)); string term = Encoding.UTF8.GetString(natsargs.Message.Data); string searchTerm = term.Replace(" ", ""); // get rid of things we do not need string msg = ""; // find the control from the data passed in var result = _context.ControlSets.Where(x => x.subControlNumber == searchTerm || x.number == searchTerm).ToList(); if (result != null && result.Count > 0) { msg = JsonConvert.SerializeObject(result.FirstOrDefault()); } else // try to get the main family description and return that { int index = GetFirstIndex(term); if (index < 0) { msg = ""; } else // see if there is a family title we can pass back { searchTerm = term.Substring(0, index).Trim(); result = _context.ControlSets.Where(x => x.subControlNumber == searchTerm || x.number == searchTerm).ToList(); if (result != null && result.Count > 0) { msg = JsonConvert.SerializeObject(result.FirstOrDefault()); } else { msg = ""; } } } // publish back out on the reply line to the calling publisher logger.Info("Sending back compressed Checklist Data"); c.Publish(natsargs.Message.Reply, Encoding.UTF8.GetBytes(Compression.CompressString(msg))); c.Flush(); // flush the line } catch (Exception ex) { // log it here logger.Error(ex, "Error retrieving control for search term {0}", Encoding.UTF8.GetString(natsargs.Message.Data)); } }; // The simple way to create an asynchronous subscriber // is to simply pass the event in. Messages will start // arriving immediately. logger.Info("setting up the OpenRMF control subscription by filter"); IAsyncSubscription asyncControls = c.SubscribeAsync("openrmf.controls", getControls); logger.Info("setting up the OpenRMF control subscription by filter"); IAsyncSubscription asyncControlByTerm = c.SubscribeAsync("openrmf.controls.search", getControlsByTerm); }
public ControlsController(ILogger <ControlsController> logger, ControlsDBContext context) { _logger = logger; _context = context; }