public DatabaseProvider() { Users = new UsersData(); Roles = new RolesData(); Households = new HouseholdsData(); Audits = new AuditData(); Permissions = new PermissionsData(); }
/// <summary> /// Perform a read against the underlying IFhirResourceHandler /// </summary> private FhirOperationResult PerformRead(string resourceType, string id, string vid) { this.ThrowIfNotReady(); // Get the services from the service registry var auditService = ApplicationContext.Current.GetService(typeof(IAuditorService)) as IAuditorService; // Stuff for auditing and exception handling AuditData audit = null; List <IResultDetail> details = new List <IResultDetail>(); FhirOperationResult result = null; try { // Get query parameters var queryParameters = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters; var resourceProcessor = FhirResourceHandlerUtil.GetResourceHandler(resourceType); if (resourceProcessor == null) // Unsupported resource { throw new FileNotFoundException("Specified resource type is not found"); } // TODO: Appropriately format response // Process incoming request result = resourceProcessor.Read(id, vid); if (result.Outcome == ResultCode.Rejected) { throw new InvalidDataException("Message was rejected"); } else if (result.Outcome == (ResultCode.NotAvailable | ResultCode.Rejected)) { throw new FileLoadException(String.Format("Resource {0} is no longer available", WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri)); } else if (result.Outcome == ResultCode.TypeNotAvailable || result.Results == null || result.Results.Count == 0) { throw new FileNotFoundException(String.Format("Resource {0} not found", WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri)); } else if (result.Outcome != ResultCode.Accepted) { throw new DataException("Read failed"); } audit = AuditUtil.CreateAuditData(result.Results); // Create the result if (result.Results != null && result.Results.Count > 0) { WebOperationContext.Current.OutgoingResponse.LastModified = result.Results[0].Timestamp; WebOperationContext.Current.OutgoingResponse.Headers.Add("Content-Disposition", String.Format("filename=\"{0}-{1}-{2}.xml\"", resourceType, result.Results[0].Id, result.Results[0].VersionId)); WebOperationContext.Current.OutgoingResponse.ETag = result.Results[0].VersionId; } return(result); } catch (Exception e) { audit = AuditUtil.CreateAuditData(null); audit.Outcome = OutcomeIndicator.EpicFail; throw; } finally { if (auditService != null) { auditService.SendAudit(audit); } } }
public JsonResult GetHomePageInfo() { if (Session["User"] is UserModel user) { HomeModel homeModel = new HomeModel(); homeModel.UserInfo = user; var chartDetails = new TransactionData().GetTransactionsLadt10Days(user.UserID); homeModel.ChartValues = new ChartOptions[chartDetails != null? chartDetails.Count : 0]; int count = 0; string formattedDate = string.Empty; foreach (var data in chartDetails) { formattedDate = data.TransactionDate.Day.ToString() + "-" + data.TransactionDate.ToString("MMM"); homeModel.ChartValues[count] = new ChartOptions { label = formattedDate, value = data.TransactionCount }; count++; ; } var audits = new AuditData().GetLast10Audit(user.UserID); homeModel.AuditInfo = new AuditModelExtended[audits != null ? audits.Count : 0]; count = 0; DateTime dt = DateTime.Now; foreach (var audit in audits) { dt = (DateTime)audit.AuditDate; homeModel.AuditInfo[count] = new AuditModelExtended { AuditInfo = audit, FormattedDay = dt.ToString("dd"), FormattedMonth = dt.ToString("MMM") }; count++; } var notifications = new NotificationData().GetNotifications(user.UserID); homeModel.Notifications = new NotificationsModelExtended[notifications != null ? notifications.Count : 0]; count = 0; foreach (var notification in notifications) { dt = notification.DateCreated; homeModel.Notifications[count] = new NotificationsModelExtended { NotificationInfo = notification, FormattedDay = dt.ToString("dd"), FormattedMonth = dt.ToString("MMM") }; count++; } var json = new JavaScriptSerializer().Serialize(homeModel); return(Json(json, JsonRequestBehavior.AllowGet)); } return(Json("", JsonRequestBehavior.AllowGet)); }
/// <summary> /// Receive a message /// </summary> protected override void OnReceiveMessage(object client) { TcpClient tcpClient = client as TcpClient; SslStream stream = new SslStream(tcpClient.GetStream(), false, new RemoteCertificateValidationCallback(RemoteCertificateValidation)); try { // Setup local and remote receive endpoint data for auditing var localEp = tcpClient.Client.LocalEndPoint as IPEndPoint; var remoteEp = tcpClient.Client.RemoteEndPoint as IPEndPoint; Uri localEndpoint = new Uri(String.Format("sllp://{0}:{1}", localEp.Address, localEp.Port)); Uri remoteEndpoint = new Uri(String.Format("sllp://{0}:{1}", remoteEp.Address, remoteEp.Port)); this.m_traceSource.TraceInfo("Accepted TCP connection from {0} > {1}", remoteEndpoint, localEndpoint); stream.AuthenticateAsServer(this.m_configuration.ServerCertificate.GetCertificate(), this.m_configuration.EnableClientCertNegotiation, System.Security.Authentication.SslProtocols.Tls, this.m_configuration.CheckCrl); // Now read to a string NHapi.Base.Parser.PipeParser parser = new NHapi.Base.Parser.PipeParser(); DateTime lastReceive = DateTime.Now; while (DateTime.Now.Subtract(lastReceive) < this.m_timeout) { int llpByte = 0; // Read LLP head byte try { llpByte = stream.ReadByte(); } catch (SocketException) { break; } if (llpByte != START_TX) // first byte must be HT { this.m_traceSource.TraceEvent(EventLevel.Warning, "Invalid LLP First Byte expected 0x{0:x} got 0x{1:x} from {2}", START_TX, llpByte, remoteEndpoint); break; } // throw new InvalidOperationException("Invalid LLP First Byte"); // Standard stream stuff, read until the stream is exhausted StringBuilder messageData = new StringBuilder(); byte[] buffer = new byte[1024]; bool receivedEOF = false, scanForCr = false; while (!receivedEOF) { int br = stream.Read(buffer, 0, 1024); messageData.Append(System.Text.Encoding.UTF8.GetString(buffer, 0, br)); // Need to check for CR? if (scanForCr) { receivedEOF = buffer[0] == END_TXNL; } else { // Look for FS int fsPos = Array.IndexOf(buffer, END_TX); if (fsPos == -1) // not found { continue; } else if (fsPos < buffer.Length - 1) // more room to read { receivedEOF = buffer[fsPos + 1] == END_TXNL; } else { scanForCr = true; // Cannot check the end of message for CR because there is no more room in the message buffer } // so need to check on the next loop } // TODO: Timeout for this } // Use the nHAPI parser to process the data Hl7MessageReceivedEventArgs messageArgs = null; try { var message = parser.Parse(messageData.ToString()); #if DEBUG this.m_traceSource.TraceInfo("Received message from sllp://{0} : {1}", tcpClient.Client.RemoteEndPoint, messageData.ToString()); #endif messageArgs = new AuthenticatedHl7MessageReceivedEventArgs(message, localEndpoint, remoteEndpoint, DateTime.Now, stream.RemoteCertificate.GetPublicKey()); HL7OperationContext.Current = new HL7OperationContext(messageArgs); // Call any bound event handlers that there is a message available OnMessageReceived(messageArgs); } finally { // Send the response back using (MemoryStream memoryWriter = new MemoryStream()) { using (StreamWriter streamWriter = new StreamWriter(memoryWriter)) { memoryWriter.Write(new byte[] { START_TX }, 0, 1); // header if (messageArgs != null && messageArgs.Response != null) { var strMessage = parser.Encode(messageArgs.Response); #if DEBUG this.m_traceSource.TraceInfo("Sending message to sllp://{0} : {1}", tcpClient.Client.RemoteEndPoint, strMessage); #endif // Since nHAPI only emits a string we just send that along the stream streamWriter.Write(strMessage); streamWriter.Flush(); } memoryWriter.Write(new byte[] { END_TX, END_TXNL }, 0, 2); // Finish the stream with FSCR stream.Write(memoryWriter.ToArray(), 0, (int)memoryWriter.Position); stream.Flush(); } } lastReceive = DateTime.Now; // Update the last receive time so the timeout function works } } } catch (AuthenticationException e) { // Trace authentication error AuditData ad = new AuditData( DateTime.Now, ActionType.Execute, OutcomeIndicator.MinorFail, EventIdentifierType.ApplicationActivity, new AuditCode("110113", "DCM") { DisplayName = "Security Alert" } ); ad.Actors = new List <AuditActorData>() { new AuditActorData() { NetworkAccessPointId = Dns.GetHostName(), NetworkAccessPointType = NetworkAccessPointType.MachineName, UserName = Environment.UserName, UserIsRequestor = false }, new AuditActorData() { NetworkAccessPointId = String.Format("sllp://{0}", tcpClient.Client.RemoteEndPoint.ToString()), NetworkAccessPointType = NetworkAccessPointType.MachineName, UserIsRequestor = true } }; ad.AuditableObjects = new List <AuditableObject>() { new AuditableObject() { Type = AuditableObjectType.SystemObject, Role = AuditableObjectRole.SecurityResource, IDTypeCode = AuditableObjectIdType.Uri, ObjectId = String.Format("sllp://{0}", this.m_listener.LocalEndpoint) } }; ApplicationServiceContext.Current.GetService <IAuditRepositoryService>()?.Insert(ad); ApplicationServiceContext.Current.GetService <IAuditDispatchService>()?.SendAudit(ad); this.m_traceSource.TraceEvent(EventLevel.Error, e.ToString()); } catch (Exception e) { this.m_traceSource.TraceEvent(EventLevel.Error, e.ToString()); // TODO: NACK } finally { stream.Close(); tcpClient.Close(); HL7OperationContext.Current = null; } }
/// <summary> /// Audit data action on FHIR interface /// </summary> private void AuditDataAction(TypeRestfulInteraction type, OutcomeIndicator outcome, params Resource[] objects) { AuditData audit = new AuditData(DateTime.Now, ActionType.Execute, outcome, EventIdentifierType.ApplicationActivity, new AuditCode(Hl7.Fhir.Utility.EnumUtility.GetLiteral(type), "http://hl7.org/fhir/ValueSet/type-restful-interaction")); AuditableObjectLifecycle lifecycle = AuditableObjectLifecycle.NotSet; switch (type) { case TypeRestfulInteraction.Create: audit.ActionCode = ActionType.Create; audit.EventIdentifier = EventIdentifierType.Import; lifecycle = AuditableObjectLifecycle.Creation; break; case TypeRestfulInteraction.Delete: audit.ActionCode = ActionType.Delete; audit.EventIdentifier = EventIdentifierType.Import; lifecycle = AuditableObjectLifecycle.LogicalDeletion; break; case TypeRestfulInteraction.HistoryInstance: case TypeRestfulInteraction.HistoryType: case TypeRestfulInteraction.SearchType: audit.ActionCode = ActionType.Execute; audit.EventIdentifier = EventIdentifierType.Query; lifecycle = AuditableObjectLifecycle.Disclosure; audit.AuditableObjects.Add(new AuditableObject() { QueryData = RestOperationContext.Current?.IncomingRequest.Url.ToString(), Role = AuditableObjectRole.Query, Type = AuditableObjectType.SystemObject, ObjectData = RestOperationContext.Current?.IncomingRequest.Headers.AllKeys.Where(o => o.Equals("accept", StringComparison.OrdinalIgnoreCase)).Select(o => new ObjectDataExtension(o, RestOperationContext.Current.IncomingRequest.Headers.Get(o))).ToList() }); break; case TypeRestfulInteraction.Update: case TypeRestfulInteraction.Patch: audit.ActionCode = ActionType.Update; audit.EventIdentifier = EventIdentifierType.Import; lifecycle = AuditableObjectLifecycle.Amendment; break; case TypeRestfulInteraction.Vread: case TypeRestfulInteraction.Read: audit.ActionCode = ActionType.Read; audit.EventIdentifier = EventIdentifierType.Query; lifecycle = AuditableObjectLifecycle.Disclosure; audit.AuditableObjects.Add(new AuditableObject() { QueryData = RestOperationContext.Current?.IncomingRequest.Url.ToString(), Role = AuditableObjectRole.Query, Type = AuditableObjectType.SystemObject, ObjectData = RestOperationContext.Current?.IncomingRequest.Headers.AllKeys.Where(o => o.Equals("accept", StringComparison.OrdinalIgnoreCase)).Select(o => new ObjectDataExtension(o, RestOperationContext.Current.IncomingRequest.Headers.Get(o))).ToList() }); break; } AuditUtil.AddLocalDeviceActor(audit); AuditUtil.AddUserActor(audit); audit.AuditableObjects.AddRange(objects.SelectMany(o => this.CreateAuditObjects(o, lifecycle))); AuditUtil.SendAudit(audit); }
/// <summary> /// A utility which can be used to send a data audit /// </summary> public static void AuditDataAction <TData>(EventTypeCodes typeCode, ActionType action, AuditableObjectLifecycle lifecycle, EventIdentifierType eventType, OutcomeIndicator outcome, String queryPerformed, params TData[] data) where TData : IdentifiedData { AuditCode eventTypeId = CreateAuditActionCode(typeCode); AuditData audit = new AuditData(DateTime.Now, action, outcome, eventType, eventTypeId); AddDeviceActor(audit); AddUserActor(audit); // Objects audit.AuditableObjects = data.Select(o => { var idTypeCode = AuditableObjectIdType.Custom; var roleCode = AuditableObjectRole.Resource; var objType = AuditableObjectType.Other; if (o is Patient) { idTypeCode = AuditableObjectIdType.PatientNumber; roleCode = AuditableObjectRole.Patient; objType = AuditableObjectType.Person; } else if (o is UserEntity || o is Provider) { idTypeCode = AuditableObjectIdType.UserIdentifier; objType = AuditableObjectType.Person; roleCode = AuditableObjectRole.Provider; } else if (o is Entity) { idTypeCode = AuditableObjectIdType.EnrolleeNumber; } else if (o is Act) { idTypeCode = AuditableObjectIdType.EncounterNumber; roleCode = AuditableObjectRole.Report; } else if (o is SecurityUser) { idTypeCode = AuditableObjectIdType.UserIdentifier; roleCode = AuditableObjectRole.SecurityUser; objType = AuditableObjectType.SystemObject; } return(new AuditableObject() { IDTypeCode = idTypeCode, CustomIdTypeCode = idTypeCode == AuditableObjectIdType.Custom ? new AuditCode(o.GetType().Name, "OpenIZTable") : null, LifecycleType = lifecycle, ObjectId = o.Key?.ToString(), Role = roleCode, Type = objType }); }).ToList(); // Query performed if (!String.IsNullOrEmpty(queryPerformed)) { audit.AuditableObjects.Add(new AuditableObject() { IDTypeCode = AuditableObjectIdType.SearchCritereon, LifecycleType = AuditableObjectLifecycle.Access, ObjectId = typeof(TData).Name, QueryData = queryPerformed, Role = AuditableObjectRole.Query, Type = AuditableObjectType.SystemObject }); } AddAncillaryObject(audit); SendAudit(audit); }
/// <summary> /// Receive a message /// </summary> protected override void OnReceiveMessage(object client) { TcpClient tcpClient = client as TcpClient; NetworkStream tcpStream = tcpClient.GetStream(); SslStream stream = new SslStream(tcpStream, false, new RemoteCertificateValidationCallback(RemoteCertificateValidation)); try { stream.AuthenticateAsServer(this.m_transportConfiguration.ServerCertificate.Certificate, this.m_transportConfiguration.TrustedClientCertificates?.Any() == true, System.Security.Authentication.SslProtocols.Tls, true); stream.ReadTimeout = (int)this.m_endpointConfiguration.ReadTimeout.TotalMilliseconds; this.ProcessSession(tcpClient, stream); } catch (AuthenticationException e) { var localEp = tcpClient.Client.LocalEndPoint as IPEndPoint; var remoteEp = tcpClient.Client.RemoteEndPoint as IPEndPoint; Uri localEndpoint = new Uri(String.Format("stcp://{0}:{1}", localEp.Address, localEp.Port)); Uri remoteEndpoint = new Uri(String.Format("stcp://{0}:{1}", remoteEp.Address, remoteEp.Port)); // Trace authentication error AuditData ad = new AuditData( DateTime.Now, ActionType.Execute, OutcomeIndicator.MinorFail, EventIdentifierType.ApplicationActivity, new AuditCode("110113", "DCM") { DisplayName = "Security Alert" } ); ad.Actors = new List <AuditActorData>() { new AuditActorData() { NetworkAccessPointId = Dns.GetHostName(), NetworkAccessPointType = NetworkAccessPointType.MachineName, UserName = Environment.UserName, UserIsRequestor = false }, new AuditActorData() { NetworkAccessPointId = String.Format("sllp://{0}", remoteEndpoint.ToString()), NetworkAccessPointType = NetworkAccessPointType.MachineName, UserIsRequestor = true } }; ad.AuditableObjects = new List <AuditableObject>() { new AuditableObject() { Type = AuditableObjectType.SystemObject, Role = AuditableObjectRole.SecurityResource, IDTypeCode = AuditableObjectIdType.Uri, ObjectId = String.Format("sllp://{0}", localEndpoint) } }; var auditService = ApplicationServiceContext.Current.GetService(typeof(IAuditDispatchService)) as IAuditDispatchService; if (auditService != null) { auditService.SendAudit(ad); } this.m_traceSource.TraceError(e.ToString()); } catch (Exception e) { this.m_traceSource.TraceError(e.ToString()); } finally { stream.Close(); tcpClient.Close(); } }
/// <summary> /// Handles a received message /// </summary> public MARC.Everest.Interfaces.IGraphable HandleMessageReceived(object sender, UnsolicitedDataEventArgs e, MARC.Everest.Connectors.IReceiveResult receivedMessage) { // audit the error IAuditorService auditor = Context.GetService(typeof(IAuditorService)) as IAuditorService; AuditData ad = new AuditData( DateTime.Now, ActionType.Execute, OutcomeIndicator.EpicFail, EventIdentifierType.ApplicationActivity, new CodeValue(String.Format("{0}", receivedMessage.Structure)) ); ad.Actors.AddRange(new List <AuditActorData>(10) { new AuditActorData() { NetworkAccessPointId = e.ReceiveEndpoint.ToString(), NetworkAccessPointType = NetworkAccessPointType.IPAddress, UserIsRequestor = false }, new AuditActorData() { NetworkAccessPointType = NetworkAccessPointType.MachineName, NetworkAccessPointId = Environment.MachineName, UserIsRequestor = false } } ); ad.AuditableObjects.Add(new AuditableObject() { IDTypeCode = AuditableObjectIdType.ReportNumber, LifecycleType = AuditableObjectLifecycle.Verification, ObjectId = (receivedMessage.Structure as IIdentifiable).Id.Root, Role = AuditableObjectRole.Subscriber, Type = AuditableObjectType.SystemObject }); if (auditor != null) { auditor.SendAudit(ad); } IInteraction solicitation = receivedMessage.Structure as IInteraction; // get the configuration ISystemConfigurationService configService = Context.GetService(typeof(ISystemConfigurationService)) as ISystemConfigurationService; // construct a generic response MCCI_IN000002CA response = new MCCI_IN000002CA( Guid.NewGuid(), DateTime.Now, new CV <ResponseMode>(ResponseMode.Immediate), MCCI_IN000002CA.GetInteractionId(), MCCI_IN000002CA.GetProfileId(), ProcessingID.Debugging, AcknowledgementCondition.Never, null, MessageUtil.CreateSender(e.ReceiveEndpoint, configService), new Acknowledgement( AcknowledgementType.ApplicationAcknowledgementReject, new TargetMessage( (receivedMessage.Structure as IIdentifiable).Id ) ) ); // Add a detail if (solicitation.InteractionId != null && solicitation.InteractionId.Extension != receivedMessage.Structure.GetType().Name) { response.Acknowledgement.AcknowledgementDetail.Add( new AcknowledgementDetail( AcknowledgementDetailType.Error, Util.ToWireFormat(MARC.Everest.RMIM.CA.R020402.Vocabulary.AcknowledgementDetailCode.ValueDoesNotMatchFixedValue), String.Format("Interaction ID '{0}' not supported for message type '{1}'", solicitation.InteractionId.Extension, receivedMessage.Structure.GetType().Name), null)); } else { response.Acknowledgement.AcknowledgementDetail.Add( new AcknowledgementDetail( AcknowledgementDetailType.Error, Util.ToWireFormat(MARC.Everest.RMIM.CA.R020402.Vocabulary.AcknowledgementDetailCode.UnsupportedInteraction), "Cannot process this interaction", null) ); } // Validation detils response.Acknowledgement.AcknowledgementDetail.AddRange(MessageUtil.CreateGenAckDetails(receivedMessage.Details)); // Populate the receiver Sender originalSolicitor = solicitation.GetType().GetProperty("Sender").GetValue(solicitation, null) as Sender; Receiver receiver = MessageUtil.CreateReceiver(originalSolicitor); response.Receiver = receiver; return(response); }
/// <summary> /// With the specified action code /// </summary> public static AuditData WithAction(this AuditData me, ActionType action) { me.ActionCode = action; return(me); }
/// <summary> /// With event type /// </summary> public static AuditData WithEventType(this AuditData me, String eventTypeCode, String eventTypeCodeSystem = "http://santedb.org/conceptset/SecurityAuditCode") { me.EventTypeCode = new AuditCode(eventTypeCode, eventTypeCodeSystem); return(me); }
/// <summary> /// Append the outcome indicator to the audit /// </summary> public static AuditData WithOutcome(this AuditData me, OutcomeIndicator outcome) { me.Outcome = outcome; return(me); }
/// <summary> /// Append user information /// </summary> public static AuditData WithUser(this AuditData me, IPrincipal principal = null) { // Use all remote endpoint providers to find the current request principal = principal ?? AuthenticationContext.Current.Principal; if (principal is IClaimsPrincipal cp) { foreach (var identity in cp.Identities) { if (identity is IDeviceIdentity && identity is IClaimsIdentity did) { me.Actors.Add(new AuditActorData() { NetworkAccessPointId = RemoteEndpointUtil.Current.GetRemoteClient()?.RemoteAddress, NetworkAccessPointType = NetworkAccessPointType.IPAddress, UserName = did.Name, ActorRoleCode = new List <AuditCode>() { new AuditCode("110153", "DCM") { DisplayName = "Source" } }, AlternativeUserId = did.FindFirst(SanteDBClaimTypes.Sid)?.Value }); } else if (identity is IApplicationIdentity && identity is IClaimsIdentity aid) { me.Actors.Add(new AuditActorData() { NetworkAccessPointId = RemoteEndpointUtil.Current.GetRemoteClient()?.RemoteAddress, NetworkAccessPointType = NetworkAccessPointType.IPAddress, UserName = aid.Name, ActorRoleCode = new List <AuditCode>() { new AuditCode("110150", "DCM") { DisplayName = "Application" } }, AlternativeUserId = aid.FindFirst(SanteDBClaimTypes.Sid)?.Value }); } else if (identity is IClaimsIdentity uid) { me.Actors.Add(new AuditActorData() { UserName = uid.Name, UserIsRequestor = true, ActorRoleCode = new List <AuditCode>() { new AuditCode("humanuser", "http://terminology.hl7.org/CodeSystem/extra-security-role-type") { DisplayName = "Human User" } }, AlternativeUserId = uid.FindFirst(SanteDBClaimTypes.Sid)?.Value }); } } } else { var actor = new AuditActorData() { NetworkAccessPointId = RemoteEndpointUtil.Current.GetRemoteClient()?.RemoteAddress, NetworkAccessPointType = NetworkAccessPointType.IPAddress, UserName = principal.Identity.Name }; if (principal.Identity is IApplicationIdentity || principal.Identity is IDeviceIdentity) { actor.ActorRoleCode.Add(new AuditCode("110153", "DCM") { DisplayName = "Source" }); } else { actor.UserIsRequestor = true; actor.ActorRoleCode.Add(new AuditCode("humanuser", "http://terminology.hl7.org/CodeSystem/extra-security-role-type")); } me.Actors.Add(actor); } return(me); }
/// <summary> /// Event identiifer set /// </summary> public static AuditData WithEventIdentifier(this AuditData me, EventIdentifierType identifier) { me.EventIdentifier = identifier; return(me); }
/// <summary> /// Add timestamp /// </summary> public static AuditData WithTimestamp(this AuditData me, DateTimeOffset?timestamp = null) { me.Timestamp = timestamp ?? DateTimeOffset.Now; return(me); }
/// <summary> /// Process a message received by the syslog message handler /// </summary> private void ProcessMessage(Syslog.TransportProtocol.SyslogMessageReceivedEventArgs e) { try { if (e == null || e.Message == null) { this.m_traceSource.TraceWarning("Received null SyslogEvent from transport"); return; } // Secured copy AuthenticatedSyslogMessageReceivedEventArgs securedEvent = e as AuthenticatedSyslogMessageReceivedEventArgs; // Process a result ApplicationServiceContext.Current.GetService <IThreadPoolService>().QueueUserWorkItem((p) => { using (AuthenticationContext.EnterSystemContext()) { try { var processResult = (ParseAuditResult)p; // Now does the audit persistence service exist? if (ApplicationServiceContext.Current.GetService <IRepositoryService <AuditBundle> >() != null) { AuditBundle insertBundle = new AuditBundle(); Audit audit = processResult.Message.ToAudit(); // Is this an error? if (audit != null) { bool alertStatus = false; // Set core properties audit.CorrelationToken = processResult.SourceMessage.CorrelationId; Uri solicitorEp = new Uri(String.Format("atna://{0}", e.SolicitorEndpoint.Host)), receiveEp = new Uri(String.Format("atna://{0}", e.ReceiveEndpoint.Host)); // Create or get node int tr = 0; var senderNode = ApplicationServiceContext.Current.GetService <IRepositoryService <AuditNode> >().Find(o => o.HostName == e.Message.HostName.ToLower(), 0, 1, out tr).FirstOrDefault(); if (senderNode == null) // Flag alert { alertStatus = true; processResult.Details.Add(new DetectedIssue(DetectedIssuePriorityType.Warning, "sender.unknown", $"The sender {e.Message.HostName} is unknown", DetectedIssueKeys.SecurityIssue)); senderNode = new AuditNode() { Key = Guid.NewGuid(), HostName = e.Message.HostName.ToLower(), Name = e.Message.HostName, Status = AuditStatusType.New, SecurityDeviceKey = ApplicationServiceContext.Current.GetService <IRepositoryService <SecurityDevice> >().Find(o => o.Name == e.Message.HostName, 0, 1, out tr).FirstOrDefault()?.Key.Value }; insertBundle.Add(senderNode); } var receiverNode = insertBundle.Item.OfType <AuditNode>().FirstOrDefault(o => o.HostName == Environment.MachineName.ToLower()) ?? ApplicationServiceContext.Current.GetService <IRepositoryService <AuditNode> >().Find(o => o.HostName == Environment.MachineName.ToLower(), 0, 1, out tr).FirstOrDefault(); if (receiverNode == null) // Flag alert { alertStatus = true; processResult.Details.Add(new DetectedIssue(DetectedIssuePriorityType.Warning, "receiver.unknown", $"The receiver {Environment.MachineName} is not registered to receive messages", DetectedIssueKeys.SecurityIssue)); receiverNode = new AuditNode() { Key = Guid.NewGuid(), HostName = Environment.MachineName.ToLower(), Name = Environment.MachineName, Status = AuditStatusType.New, SecurityDeviceKey = ApplicationServiceContext.Current.GetService <IRepositoryService <SecurityDevice> >().Find(o => o.Name == Environment.MachineName, 0, 1, out tr).FirstOrDefault()?.Key.Value }; insertBundle.Add(receiverNode); } // Create or get session var session = ApplicationServiceContext.Current.GetService <IRepositoryService <AuditSession> >().Get(processResult.SourceMessage.SessionId); if (session == null) { insertBundle.Add(new AuditSession() { Key = processResult.SourceMessage.SessionId, Receiver = receiverNode, Sender = senderNode, ReceivingEndpoint = receiveEp.ToString(), SenderEndpoint = solicitorEp.ToString() }); } // Get the bundle ready ... audit.CorrelationToken = processResult.SourceMessage.CorrelationId; audit.IsAlert = alertStatus; audit.ProcessId = e.Message.ProcessId; audit.ProcessName = e.Message.ProcessName; audit.CreationTime = e.Timestamp; audit.SessionKey = processResult.SourceMessage.SessionId; audit.Status = AuditStatusType.New; audit.Details = processResult.Details?.Select(i => new AuditDetailData() { Key = Guid.NewGuid(), Message = i.Text, IssueType = (DetectedIssuePriorityType)Enum.Parse(typeof(DetectedIssuePriorityType), i.Priority.ToString()) }).ToList(); insertBundle.Add(audit); } else if (processResult.Details.Count() > 0) { foreach (var i in processResult.Details.Where(o => o.Priority != DetectedIssuePriorityType.Information)) { insertBundle.Add(new AuditDetailData() { Key = Guid.NewGuid(), SourceEntityKey = audit.CorrelationToken, Message = i.Text, IssueType = i.Priority == DetectedIssuePriorityType.Error ? DetectedIssuePriorityType.Error : DetectedIssuePriorityType.Warning }); } } // Batch persistence service ApplicationServiceContext.Current.GetService <IRepositoryService <AuditBundle> >().Insert(insertBundle); } else { // Use "classic" mode AuditData audit = processResult.Message.ToAuditData(); audit.AddMetadata(AuditMetadataKey.LocalEndpoint, e.ReceiveEndpoint.ToString()); audit.AddMetadata(AuditMetadataKey.ProcessName, e.Message.ProcessName); audit.AddMetadata(AuditMetadataKey.RemoteHost, e.SolicitorEndpoint.ToString()); audit.AddMetadata(AuditMetadataKey.SessionId, e.Message.SessionId.ToString()); audit.AddMetadata(AuditMetadataKey.SubmissionTime, e.Message.Timestamp.ToString("o")); AuditUtil.SendAudit(audit); } } catch (Exception ex) { this.m_traceSource.TraceError("Error persisting audit: {0}", ex); } } }, MessageUtil.ParseAudit(e.Message)); } catch (Exception ex) { this.m_traceSource.TraceError(ex.ToString()); throw; } }
/// <summary> /// Insert audit data /// </summary> public AuditData Insert(AuditData audit) { var conn = this.CreateConnection(); using (conn.Lock()) { try { conn.BeginTransaction(); // Insert core var dbAudit = this.m_mapper.MapModelInstance <AuditData, DbAuditData>(audit); var eventId = audit.EventTypeCode; if (eventId != null) { var existing = conn.Table <DbAuditCode>().Where(o => o.Code == eventId.Code && o.CodeSystem == eventId.CodeSystem).FirstOrDefault(); if (existing == null) { Guid codeId = Guid.NewGuid(); dbAudit.EventTypeCode = codeId.ToByteArray(); conn.Insert(new DbAuditCode() { Code = eventId.Code, CodeSystem = eventId.CodeSystem, Id = codeId.ToByteArray() }); } else { dbAudit.EventTypeCode = existing.Id; } } dbAudit.CreationTime = DateTime.Now; audit.CorrelationToken = Guid.NewGuid(); dbAudit.Id = audit.CorrelationToken.ToByteArray(); conn.Insert(dbAudit); // Insert secondary properties if (audit.Actors != null) { foreach (var act in audit.Actors) { var dbAct = conn.Table <DbAuditActor>().Where(o => o.UserName == act.UserName).FirstOrDefault(); if (dbAct == null) { dbAct = this.m_mapper.MapModelInstance <AuditActorData, DbAuditActor>(act); dbAct.Id = Guid.NewGuid().ToByteArray(); conn.Insert(dbAct); var roleCode = act.ActorRoleCode?.FirstOrDefault(); if (roleCode != null) { var existing = conn.Table <DbAuditCode>().Where(o => o.Code == roleCode.Code && o.CodeSystem == roleCode.CodeSystem).FirstOrDefault(); if (existing == null) { dbAct.ActorRoleCode = Guid.NewGuid().ToByteArray(); conn.Insert(new DbAuditCode() { Code = roleCode.Code, CodeSystem = roleCode.CodeSystem, Id = dbAct.ActorRoleCode }); } else { dbAct.ActorRoleCode = existing.Id; } } } conn.Insert(new DbAuditActorAssociation() { TargetUuid = dbAct.Id, SourceUuid = dbAudit.Id, Id = Guid.NewGuid().ToByteArray() }); } } // Audit objects if (audit.AuditableObjects != null) { foreach (var ao in audit.AuditableObjects) { var dbAo = this.m_mapper.MapModelInstance <AuditableObject, DbAuditObject>(ao); dbAo.IDTypeCode = (int)(ao.IDTypeCode ?? 0); dbAo.LifecycleType = (int)(ao.LifecycleType ?? 0); dbAo.Role = (int)(ao.Role ?? 0); dbAo.Type = (int)(ao.Type); dbAo.AuditId = dbAudit.Id; dbAo.Id = Guid.NewGuid().ToByteArray(); conn.Insert(dbAo); } } conn.Commit(); return(audit); } catch (Exception ex) { conn.Rollback(); this.m_tracer.TraceError("Error inserting audit: {0}", ex); throw; } } }
/// <summary> /// Get all merge candidates /// </summary> public ConflictCollection GetConflicts(int offset, int count, bool identifierOnly) { // Get all Services IAuditorService auditSvc = ApplicationContext.CurrentContext.GetService(typeof(IAuditorService)) as IAuditorService; IDataPersistenceService repSvc = ApplicationContext.CurrentContext.GetService(typeof(IDataPersistenceService)) as IDataPersistenceService; IClientRegistryMergeService mergeSvc = ApplicationContext.CurrentContext.GetService(typeof(IClientRegistryMergeService)) as IClientRegistryMergeService; // Audit message AuditData audit = this.ConstructAuditData(ActionType.Read, EventIdentifierType.Export); audit.EventTypeCode = new CodeValue("ADM_GetConflicts"); try { // Get all with a merge var mergeResults = mergeSvc.GetOutstandingConflicts(); var retVal = new ConflictCollection(); retVal.Count = mergeResults.Count(); // Loop and load foreach (var merge in mergeResults.Skip(offset).Take(count)) { // Construct the return, and load match Conflict conf = new Conflict(); if (!identifierOnly) { conf.Source = repSvc.GetContainer(merge, true) as RegistrationEvent; // Add audit data audit.AuditableObjects.Add(new AuditableObject() { IDTypeCode = AuditableObjectIdType.ReportNumber, LifecycleType = AuditableObjectLifecycle.Export, ObjectId = String.Format("{0}^^^&{1}&ISO", conf.Source.AlternateIdentifier.Identifier, conf.Source.AlternateIdentifier.Domain), Role = AuditableObjectRole.MasterFile, Type = AuditableObjectType.SystemObject, QueryData = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("loadFast=false")) }); } // Load the matches foreach (var match in mergeSvc.GetConflicts(merge)) { if (!identifierOnly) { var matchRecord = repSvc.GetContainer(match, true) as RegistrationEvent; conf.Match.Add(matchRecord); // Add audit data audit.AuditableObjects.Add(new AuditableObject() { IDTypeCode = AuditableObjectIdType.ReportNumber, LifecycleType = AuditableObjectLifecycle.Export, ObjectId = String.Format("{0}^^^&{1}&ISO", matchRecord.AlternateIdentifier.Identifier, matchRecord.AlternateIdentifier.Domain), Role = AuditableObjectRole.MasterFile, Type = AuditableObjectType.SystemObject, QueryData = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("loadFast=false")) }); } else { conf.Match.Add(new RegistrationEvent() { AlternateIdentifier = match }); } } retVal.Conflict.Add(conf); } return(retVal); } catch (Exception e) { Trace.TraceError("Could not execute GetConflicts : {0}", e.ToString()); audit.Outcome = OutcomeIndicator.EpicFail; #if DEBUG throw new FaultException(new FaultReason(e.ToString()), new FaultCode(e.GetType().Name)); #else throw new FaultException(new FaultReason(e.Message), new FaultCode(e.GetType().Name)); #endif } finally { if (auditSvc != null) { auditSvc.SendAudit(audit); } } }
/// <summary> /// Hydrate the query /// </summary> /// <param name="queryId"></param> /// <returns></returns> private BisResultContext HydrateQuery(String queryId) { AuditData audit = new AuditData(DateTimeOffset.Now, ActionType.Execute, OutcomeIndicator.Success, EventIdentifierType.Query, AuditUtil.CreateAuditActionCode(EventTypeCodes.SecondaryUseQuery)); try { // First we want to grab the appropriate source for this ID var viewDef = this.m_metadataRepository.Get <BiViewDefinition>(queryId); if (viewDef == null) { var queryDef = this.m_metadataRepository.Get <BiQueryDefinition>(queryId); if (queryDef == null) // Parameter value { var parmDef = this.m_metadataRepository.Get <BiParameterDefinition>(queryId); if (parmDef == null) { throw new KeyNotFoundException($"Could not find a Parameter, Query or View to hydrate named {queryId}"); } queryDef = parmDef?.Values as BiQueryDefinition; queryDef.Id = queryDef.Id ?? queryId; } viewDef = new BiViewDefinition() { Id = queryDef.Id, Query = queryDef }; } viewDef = SanteDB.BI.Util.BiUtils.ResolveRefs(viewDef) as BiViewDefinition; var dsource = viewDef.Query?.DataSources.FirstOrDefault(o => o.Name == "main") ?? viewDef.Query?.DataSources.FirstOrDefault(); if (dsource == null) { throw new KeyNotFoundException("Query does not contain a data source"); } IBiDataSource providerImplementation = null; if (dsource.ProviderType != null && this.m_metadataRepository.IsLocal) { providerImplementation = this.m_serviceManager.CreateInjected(dsource.ProviderType) as IBiDataSource; } else { providerImplementation = ApplicationServiceContext.Current.GetService <IBiDataSource>(); // Global default } // Populate data about the query audit.AuditableObjects.Add(new AuditableObject() { IDTypeCode = AuditableObjectIdType.ReportNumber, LifecycleType = AuditableObjectLifecycle.Report, ObjectId = queryId, QueryData = RestOperationContext.Current.IncomingRequest.Url.Query, Role = AuditableObjectRole.Query, Type = AuditableObjectType.SystemObject }); var parameters = this.CreateParameterDictionary(); // Aggregations and groups? if (RestOperationContext.Current.IncomingRequest.QueryString["_groupBy"] != null) { var aggRx = new Regex(@"(\w*)\((.*?)\)"); viewDef.AggregationDefinitions = new List <BiAggregationDefinition>() { new BiAggregationDefinition() { Groupings = RestOperationContext.Current.IncomingRequest.QueryString.GetValues("_groupBy").Select(o => new BiSqlColumnReference() { ColumnSelector = o.Contains("::") ? $"CAST({o.Substring(0, o.IndexOf(":"))} AS {o.Substring(o.IndexOf(":") + 2)})" : o, Name = o.Contains("::") ? o.Substring(0, o.IndexOf(":")) : o }).ToList(), Columns = RestOperationContext.Current.IncomingRequest.QueryString.GetValues("_select").Select(o => { var match = aggRx.Match(o); if (!match.Success) { throw new InvalidOperationException("Aggregation function must be in format AGGREGATOR(COLUMN)"); } return(new BiAggregateSqlColumnReference() { Aggregation = (BiAggregateFunction)Enum.Parse(typeof(BiAggregateFunction), match.Groups[1].Value, true), ColumnSelector = match.Groups[2].Value, Name = match.Groups[2].Value }); }).ToList() } }; } int offset = 0, count = 100; if (!Int32.TryParse(RestOperationContext.Current.IncomingRequest.QueryString["_offset"] ?? "0", out offset)) { throw new FormatException("_offset is not in the correct format"); } if (!Int32.TryParse(RestOperationContext.Current.IncomingRequest.QueryString["_count"] ?? "100", out count)) { throw new FormatException("_count is not in the correct format"); } var queryData = providerImplementation.ExecuteView(viewDef, parameters, offset, count); return(queryData); } catch (KeyNotFoundException) { audit.Outcome = OutcomeIndicator.MinorFail; throw; } catch (Exception e) { audit.Outcome = OutcomeIndicator.MinorFail; this.m_tracer.TraceError("Error rendering query: {0}", e); throw new FaultException(500, $"Error rendering query {queryId}", e); } finally { AuditUtil.AddLocalDeviceActor(audit); AuditUtil.AddUserActor(audit); AuditUtil.SendAudit(audit); } }
/// <summary> /// Get recent activity /// </summary> public RegistrationEventCollection GetRecentActivity(TimestampSet timeRange, int offset, int count, bool identifierOnly) { // Get all Services IAuditorService auditSvc = ApplicationContext.CurrentContext.GetService(typeof(IAuditorService)) as IAuditorService; IDataRegistrationService regSvc = ApplicationContext.CurrentContext.GetService(typeof(IDataRegistrationService)) as IDataRegistrationService; IDataPersistenceService repSvc = ApplicationContext.CurrentContext.GetService(typeof(IDataPersistenceService)) as IDataPersistenceService; // Audit message AuditData audit = this.ConstructAuditData(ActionType.Read, EventIdentifierType.Export); audit.EventTypeCode = new CodeValue("ADM_GetRegistrations"); try { // Result identifiers VersionedDomainIdentifier[] vids = null; var dummyQuery = new QueryEvent(); dummyQuery.Add(new RegistrationEvent() { EventClassifier = RegistrationEventType.Register, EffectiveTime = timeRange }, "SUBJ", SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.SubjectOf, null); vids = regSvc.QueryRecord(dummyQuery); RegistrationEventCollection retVal = new RegistrationEventCollection(); Object syncLock = new object(); retVal.Count = vids.Length; // Now fetch each one asynchronously if (!identifierOnly) { using (WaitThreadPool thdPool = new WaitThreadPool(Environment.ProcessorCount * 2)) { foreach (var id in vids.Skip(offset).Take(count)) { thdPool.QueueUserWorkItem( delegate(object state) { try { var itm = repSvc.GetContainer(state as VersionedDomainIdentifier, true); lock (syncLock) retVal.Event.Add(itm as RegistrationEvent); } catch (Exception e) { Trace.TraceError("Could not fetch result {0} : {1}", (state as VersionedDomainIdentifier).Identifier, e.ToString()); } } , id); } // Wait until fetch is done thdPool.WaitOne(new TimeSpan(0, 0, 30), false); } //retVal.Event.Sort((a, b) => b.Timestamp.CompareTo(a.Timestamp)); // Add audit data foreach (var res in retVal.Event) { audit.AuditableObjects.Add(new AuditableObject() { IDTypeCode = AuditableObjectIdType.ReportNumber, LifecycleType = AuditableObjectLifecycle.Export, ObjectId = String.Format("{0}^^^&{1}&ISO", res.AlternateIdentifier.Identifier, res.AlternateIdentifier.Domain), Role = AuditableObjectRole.MasterFile, Type = AuditableObjectType.SystemObject, QueryData = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("loadFast=true")) }); } } return(retVal); } catch (Exception e) { Trace.TraceError("Could not execute GetRegistrations : {0}", e.ToString()); audit.Outcome = OutcomeIndicator.EpicFail; #if DEBUG throw new FaultException(new FaultReason(e.ToString()), new FaultCode(e.GetType().Name)); #else throw new FaultException(new FaultReason(e.Message), new FaultCode(e.GetType().Name)); #endif } finally { if (auditSvc != null) { auditSvc.SendAudit(audit); } } }
/// <summary> /// Audit internal resources. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="message">The message.</param> /// <param name="idType">Type of the identifier.</param> /// <param name="lifecycle">The lifecycle.</param> /// <param name="role">The role.</param> /// <param name="type">The type.</param> /// <param name="objectKeyPropertyName">Name of the object key property.</param> /// <param name="objectKeyClassifier">The object key classifier.</param> /// <param name="includeDetail">if set to <c>true</c> [include detail].</param> /// <param name="objects">The objects.</param> /// <exception cref="System.ArgumentNullException">objectKeyPropertyName /// or /// message</exception> /// <exception cref="System.ArgumentException">objectKeyPropertyName</exception> protected void AddObjectInfoEx <T>(AuditData message, AuditableObjectIdType idType, AuditableObjectLifecycle lifecycle, AuditableObjectRole role, AuditableObjectType type, string objectKeyPropertyName, string objectKeyClassifier = null, bool includeDetail = false, IEnumerable <T> objects = null) { if (objects == null) { return; } // Validate parameters if (objectKeyPropertyName == null) { throw new ArgumentNullException(nameof(objectKeyPropertyName)); } if (message == null) { throw new ArgumentNullException(nameof(message)); } // Get key property var objectKeyProperty = typeof(T).GetProperty(objectKeyPropertyName); if (objectKeyProperty == null) { throw new ArgumentException("objectKeyPropertyName"); } var idScope = typeof(T).Name; // Audit objects foreach (var obj in objects) { if (obj == null) { continue; } var auditableObject = new AuditableObject { IDTypeCode = idType, LifecycleType = lifecycle, Role = role, Type = type, ObjectId = idType == AuditableObjectIdType.Uri ? objectKeyProperty.GetValue(obj).ToString() : $"{objectKeyProperty.GetValue(obj)}^^^{objectKeyClassifier ?? idScope}" }; if (includeDetail) { string typeName = null; if (obj.GetType().GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Any() && obj.GetType().FullName.Contains("AnonymousType")) { typeName = objectKeyClassifier ?? idScope; } var detail = CreateObjectDataExtension(obj, name: typeName); auditableObject.ObjectData.Add(detail); } message.AuditableObjects.Add(auditableObject); } }
/// <summary> /// 根据审计信息组织新审计数据,按审计配置过滤 /// </summary> /// <param name="db"></param> /// <param name="user"></param> /// <param name="audit"></param> /// <param name="dbInfo"></param> /// <returns></returns> internal static List <AuditData> AuditConvertToArgs(DatabaseFacade db, UserContext user, Z.EntityFramework.Plus.Audit audit, DbInfo dbInfo) { var id = Guid.NewGuid().ToString("N");//LogEx.GetTransactionId(); var cfgs = GetAuditConfig(user, dbInfo); var dbName = db.GetDbConnection().Database; List <AuditData> list = new List <AuditData>(); if (cfgs == null || cfgs.Count <= 0) { return(list); } audit?.Entries.ForEach(x => { var auditColumns = GetAuditColumns(cfgs, dbName, x.EntityTypeName); // 增加判断空 if (x != null && auditColumns != null && auditColumns.Count > 0) { var hasAuditColumn = x.Properties?.Any(o => auditColumns.Contains(o?.PropertyName?.ToLower())) ?? false; if (hasAuditColumn) //有审计列则do { AuditData data = new AuditData() { TableName = x.EntityTypeName, AuditId = Guid.NewGuid().ToString("N"), IsSql = false, StateName = x.StateName, TransactionId = id, CreatedDate = DateTime.Now, Ttid = user.TTID, UserId = user.LoginName, SysId = cfgs[0].SysId, PrimarkKey = GetPrimaryValue(GetPrimaryKey(cfgs, dbName, x.EntityTypeName), x.Properties, x.Entity) }; x.Properties?.ForEach(y => { if (auditColumns.Contains(y.PropertyName?.ToLower())) { var p = GetAuditDataLine(y, data.AuditId); if (p != null) { data.Properties.Add(p); } } }); //过滤新旧值都相同的记录,产生的原因是 某些字段未在审计配置中,但是按审计配置 无法剔除主键 if (x.State == Z.EntityFramework.Plus.AuditEntryState.EntityModified && (data.Properties?.All(o => o.NewValueFormatted == o.OldValueFormatted) ?? true)) { //判断有点难懂,留空 } else { list.Add(data); } } } }); return(list); }
/// <summary> /// Send specified audit /// </summary> internal static void SendAudit(AuditData audit) { ApplicationContext.Current.GetService <IAuditorService>()?.SendAudit(audit); }
/// <summary> /// Create audit data /// </summary> internal AuditData CreateAuditData(string itiName, ActionType action, OutcomeIndicator outcome, Hl7MessageReceivedEventArgs msgEvent, List <VersionedDomainIdentifier> identifiers) { // Audit data AuditData retVal = null; AuditableObjectLifecycle lifecycle = AuditableObjectLifecycle.Access; // Get the config service ISystemConfigurationService config = Context.GetService(typeof(ISystemConfigurationService)) as ISystemConfigurationService; Terser terser = new Terser(msgEvent.Message); // Source and dest string sourceData = String.Format("{0}|{1}", terser.Get("/MSH-3"), terser.Get("/MSH-4")), destData = String.Format("{0}|{1}", terser.Get("/MSH-5"), terser.Get("/MSH-6")); switch (itiName) { case "ITI-21": { retVal = new AuditData(DateTime.Now, action, outcome, EventIdentifierType.Query, new CodeValue(itiName, "IHE Transactions") { DisplayName = "Patient Demographics Query" }); // Audit actor for Patient Identity Source retVal.Actors.Add(new AuditActorData() { UserIsRequestor = true, UserIdentifier = sourceData, ActorRoleCode = new List <CodeValue>() { new CodeValue("110153", "DCM") { DisplayName = "Source" } }, NetworkAccessPointId = msgEvent.SolicitorEndpoint.Host, NetworkAccessPointType = msgEvent.SolicitorEndpoint.HostNameType == UriHostNameType.Dns ? NetworkAccessPointType.MachineName : NetworkAccessPointType.IPAddress }); // Add query parameters retVal.AuditableObjects.Add( new AuditableObject() { IDTypeCode = AuditableObjectIdType.Custom, CustomIdTypeCode = new CodeValue(itiName, "IHE Transactions") { DisplayName = "Patient Demographics Query" }, QueryData = Convert.ToBase64String(CreateMessageSerialized(msgEvent.Message)), Type = AuditableObjectType.SystemObject, Role = AuditableObjectRole.Query, ObjectId = terser.Get("/QPD-2"), ObjectData = new Dictionary <string, byte[]>() { { "MSH-10", System.Text.Encoding.ASCII.GetBytes(terser.Get("/MSH-10")) } } } ); // Audit actor for PDQ retVal.Actors.Add(new AuditActorData() { UserIdentifier = destData, UserIsRequestor = false, ActorRoleCode = new List <CodeValue>() { new CodeValue("110152", "DCM") { DisplayName = "Destination" } }, NetworkAccessPointType = NetworkAccessPointType.MachineName, NetworkAccessPointId = Dns.GetHostName(), AlternativeUserId = Process.GetCurrentProcess().Id.ToString() }); break; } case "ITI-8": { retVal = new AuditData(DateTime.Now, action, outcome, EventIdentifierType.PatientRecord, new CodeValue(itiName, "IHE Transactions") { DisplayName = "Patient Identity Feed" }); // Audit actor for Patient Identity Source retVal.Actors.Add(new AuditActorData() { UserIsRequestor = true, UserIdentifier = sourceData, ActorRoleCode = new List <CodeValue>() { new CodeValue("110153", "DCM") { DisplayName = "Source" } }, NetworkAccessPointId = msgEvent.SolicitorEndpoint.Host, NetworkAccessPointType = msgEvent.SolicitorEndpoint.HostNameType == UriHostNameType.Dns ? NetworkAccessPointType.MachineName : NetworkAccessPointType.IPAddress }); // Audit actor for PDQ retVal.Actors.Add(new AuditActorData() { UserIdentifier = destData, UserIsRequestor = false, ActorRoleCode = new List <CodeValue>() { new CodeValue("110152", "DCM") { DisplayName = "Destination" } }, NetworkAccessPointType = NetworkAccessPointType.MachineName, NetworkAccessPointId = Dns.GetHostName(), AlternativeUserId = Process.GetCurrentProcess().Id.ToString() }); break; } case "ITI-9": { retVal = new AuditData(DateTime.Now, action, outcome, EventIdentifierType.Query, new CodeValue(itiName, "IHE Transactions") { DisplayName = "PIX Query" }); // Audit actor for Patient Identity Source retVal.Actors.Add(new AuditActorData() { UserIsRequestor = true, UserIdentifier = sourceData, ActorRoleCode = new List <CodeValue>() { new CodeValue("110153", "DCM") { DisplayName = "Source" } }, NetworkAccessPointId = msgEvent.SolicitorEndpoint.Host, NetworkAccessPointType = msgEvent.SolicitorEndpoint.HostNameType == UriHostNameType.Dns ? NetworkAccessPointType.MachineName : NetworkAccessPointType.IPAddress }); // Add query parameters retVal.AuditableObjects.Add( new AuditableObject() { IDTypeCode = AuditableObjectIdType.Custom, CustomIdTypeCode = new CodeValue("ITI-9", "IHE Transactions") { DisplayName = "PIX Query" }, QueryData = Convert.ToBase64String(CreateMessageSerialized(msgEvent.Message)), Type = AuditableObjectType.SystemObject, Role = AuditableObjectRole.Query, ObjectId = terser.Get("/QPD-2"), ObjectData = new Dictionary <string, byte[]>() { { "MSH-10", System.Text.Encoding.ASCII.GetBytes(terser.Get("/MSH-10")) } } } ); // Audit actor for PDQ retVal.Actors.Add(new AuditActorData() { UserIdentifier = destData, UserIsRequestor = false, ActorRoleCode = new List <CodeValue>() { new CodeValue("110152", "DCM") { DisplayName = "Destination" } }, NetworkAccessPointType = NetworkAccessPointType.MachineName, NetworkAccessPointId = Dns.GetHostName(), AlternativeUserId = Process.GetCurrentProcess().Id.ToString() }); break; } } var expDatOid = config.OidRegistrar.GetOid("CR_CID"); // HACK: Use only patient identifiers in the output foreach (var id in identifiers.Where(o => o.Domain != expDatOid.Oid).ToArray()) { RegistrationEvent evt = this.m_dataPersistence.GetContainer(id, true) as RegistrationEvent; if (evt != null) { identifiers.Remove(id); foreach (Person subj in evt.FindAllComponents(HealthServiceRecordSiteRoleType.SubjectOf)) { identifiers.Add(new VersionedDomainIdentifier() { Identifier = subj.Id.ToString(), Domain = expDatOid.Oid }); } } } // Audit patients foreach (var id in identifiers) { // If the id is not a patient then // Construct the audit object AuditableObject aud = new AuditableObject() { IDTypeCode = AuditableObjectIdType.PatientNumber, Role = AuditableObjectRole.Patient, Type = AuditableObjectType.Person }; // Lifecycle switch (action) { case ActionType.Create: aud.LifecycleType = AuditableObjectLifecycle.Creation; break; case ActionType.Delete: aud.LifecycleType = AuditableObjectLifecycle.LogicalDeletion; break; case ActionType.Execute: aud.LifecycleType = AuditableObjectLifecycle.Access; break; case ActionType.Read: aud.LifecycleType = AuditableObjectLifecycle.Disclosure; break; case ActionType.Update: aud.LifecycleType = AuditableObjectLifecycle.Amendment; break; } aud.ObjectData.Add("MSH-10", System.Text.Encoding.ASCII.GetBytes(terser.Get("/MSH-10"))); aud.ObjectId = String.Format("{1}^^^{2}&{0}&ISO", expDatOid.Oid, id.Identifier, expDatOid.Attributes.Find(o => o.Key == "AssigningAuthorityName").Value); retVal.AuditableObjects.Add(aud); } return(retVal); }
/// <summary> /// Start auditor service /// </summary> public bool Start() { this.Starting?.Invoke(this, EventArgs.Empty); this.m_safeToStop = false; ApplicationContext.Current.Started += (o, e) => { try { this.m_tracer.TraceInfo("Binding to service events..."); ApplicationContext.Current.GetService <IIdentityProviderService>().Authenticated += (so, se) => { if ((se.Principal?.Identity.Name ?? se.UserName).ToLower() != ApplicationContext.Current.Configuration.GetSection <SecurityConfigurationSection>().DeviceName.ToLower()) { AuditUtil.AuditLogin(se.Principal, se.UserName, so as IIdentityProviderService, se.Success); } }; ApplicationContext.Current.GetService <QueueManagerService>().QueueExhausted += (so, se) => { if (se.ObjectKeys.Count() > 0) { switch (se.Queue) { case "inbound": if (SynchronizationQueue.Inbound.Count() == 0) { AuditUtil.AuditDataAction <IdentifiedData>(EventTypeCodes.Import, ActionType.Create, AuditableObjectLifecycle.Import, EventIdentifierType.Import, OutcomeIndicator.Success, null); } break; case "outbound": if (SynchronizationQueue.Outbound.Count() == 0) { AuditUtil.AuditDataAction <IdentifiedData>(EventTypeCodes.Export, ActionType.Execute, AuditableObjectLifecycle.Export, EventIdentifierType.Export, OutcomeIndicator.Success, null); } break; } } }; // Scan for IRepositoryServices and bind to their events as well foreach (var svc in ApplicationContext.Current.GetServices().OfType <IAuditEventSource>()) { svc.DataCreated += (so, se) => { if (se.Objects.Any(x => x is Entity || x is Act) && AuthenticationContext.Current.Principal.Identity.Name.ToLower() != ApplicationContext.Current.Configuration.GetSection <SecurityConfigurationSection>().DeviceName.ToLower()) { AuditUtil.AuditDataAction(EventTypeCodes.PatientRecord, ActionType.Create, AuditableObjectLifecycle.Creation, EventIdentifierType.PatientRecord, se.Success ? OutcomeIndicator.Success : OutcomeIndicator.SeriousFail, null, se.Objects.OfType <IdentifiedData>().ToArray()); } }; svc.DataUpdated += (so, se) => { if (se.Objects.Any(x => x is Entity || x is Act) && AuthenticationContext.Current.Principal.Identity.Name.ToLower() != ApplicationContext.Current.Configuration.GetSection <SecurityConfigurationSection>().DeviceName.ToLower()) { AuditUtil.AuditDataAction(EventTypeCodes.PatientRecord, ActionType.Update, AuditableObjectLifecycle.Amendment, EventIdentifierType.PatientRecord, se.Success ? OutcomeIndicator.Success : OutcomeIndicator.SeriousFail, null, se.Objects.OfType <IdentifiedData>().ToArray()); } }; svc.DataObsoleted += (so, se) => { if (se.Objects.Any(x => x is Entity || x is Act) && AuthenticationContext.Current.Principal.Identity.Name.ToLower() != ApplicationContext.Current.Configuration.GetSection <SecurityConfigurationSection>().DeviceName.ToLower()) { AuditUtil.AuditDataAction(EventTypeCodes.PatientRecord, ActionType.Delete, AuditableObjectLifecycle.LogicalDeletion, EventIdentifierType.PatientRecord, se.Success ? OutcomeIndicator.Success : OutcomeIndicator.SeriousFail, null, se.Objects.OfType <IdentifiedData>().ToArray()); } }; svc.DataDisclosed += (so, se) => { if (se.Objects.Count() > 0 && se.Objects.Any(i => i is Patient || i is Act) && AuthenticationContext.Current.Principal.Identity.Name.ToLower() != ApplicationContext.Current.Configuration.GetSection <SecurityConfigurationSection>().DeviceName.ToLower() && AuthenticationContext.Current.Principal.Identity.Name.ToLower() != "system") { AuditUtil.AuditDataAction(EventTypeCodes.Query, ActionType.Read, AuditableObjectLifecycle.Disclosure, EventIdentifierType.Query, se.Success ? OutcomeIndicator.Success : OutcomeIndicator.SeriousFail, se.Query, se.Objects.OfType <IdentifiedData>().ToArray()); } }; if (svc is ISecurityAuditEventSource) { (svc as ISecurityAuditEventSource).SecurityAttributesChanged += (so, se) => AuditUtil.AuditSecurityAttributeAction(se.Objects, se.Success, se.ChangedProperties); } } AuditUtil.AuditApplicationStartStop(EventTypeCodes.ApplicationStart); } catch (Exception ex) { this.m_tracer.TraceError("Error starting up audit repository service: {0}", ex); } }; ApplicationContext.Current.Stopped += (o, e) => AuditUtil.AuditApplicationStartStop(EventTypeCodes.ApplicationStop); ApplicationContext.Current.Stopping += (o, e) => this.m_safeToStop = true; AuditInfo sendAudit = new AuditInfo(); // Send audit Action <Object> timerQueue = null; timerQueue = o => { lock (sendAudit) if (sendAudit.Audit.Count > 0) { SynchronizationQueue.Admin.Enqueue(new AuditInfo() { Audit = new List <AuditData>(sendAudit.Audit) }, Synchronization.Model.DataOperationType.Insert); sendAudit.Audit.Clear(); } ApplicationContext.Current.GetService <IThreadPoolService>().QueueUserWorkItem(new TimeSpan(0, 0, 30), timerQueue, null); }; // Queue user work item for sending ApplicationContext.Current.GetService <IThreadPoolService>().QueueUserWorkItem(new TimeSpan(0, 0, 30), timerQueue, null); // Queue pooled item ApplicationContext.Current.GetService <IThreadPoolService>().QueueNonPooledWorkItem(o => { while (!this.m_safeToStop) { try { this.m_resetEvent.WaitOne(); while (this.m_auditQueue.Count > 0) { AuditData ad = null; lock (this.m_auditQueue) ad = this.m_auditQueue.Dequeue(); try { // First, save the audit locally var ar = ApplicationContext.Current.GetService <IAuditRepositoryService>(); if (ar == null) { throw new InvalidOperationException("!!SECURITY ALERT!! >> Cannot find audit repository"); } ad = ar.Insert(ad); lock (sendAudit) sendAudit.Audit.Add(ad); } catch (Exception e) { this.m_tracer.TraceError("!!SECURITY ALERT!! >> Error sending audit {0}: {1}", ad, e); } } } catch (Exception e) { this.m_tracer.TraceError("!!SECURITY ALERT!! >> Error polling audit task list {0}", e); } } }, null); this.Started?.Invoke(this, EventArgs.Empty); return(true); }
public AuditData AuditOrganisation(UpdateOrganisationCommand command) { var auditChanges = new List <AuditData>(); var auditChangesMade = AuditLegalName(command.OrganisationId, command.Username, command.LegalName); if (auditChangesMade.ChangesMade) { auditChanges.Add(auditChangesMade); } auditChangesMade = AuditTradingName(command.OrganisationId, command.Username, command.TradingName); if (auditChangesMade.ChangesMade) { auditChanges.Add(auditChangesMade); } auditChangesMade = AuditProviderType(command.OrganisationId, command.Username, command.ProviderTypeId, command.OrganisationTypeId); if (auditChangesMade.ChangesMade) { auditChanges.Add(auditChangesMade); } auditChangesMade = AuditCompanyNumber(command.OrganisationId, command.Username, command.CompanyNumber); if (auditChangesMade.ChangesMade) { auditChanges.Add(auditChangesMade); } auditChangesMade = AuditCharityNumber(command.OrganisationId, command.Username, command.CharityNumber); if (auditChangesMade.ChangesMade) { auditChanges.Add(auditChangesMade); } auditChangesMade = AuditApplicationDeterminedDate(command.OrganisationId, command.Username, command.ApplicationDeterminedDate); if (auditChangesMade.ChangesMade) { auditChanges.Add(auditChangesMade); } var auditDetailsReturned = new AuditData { FieldChanges = new List <AuditLogEntry>() }; if (auditChanges.Any()) { auditDetailsReturned.OrganisationId = command.OrganisationId; auditDetailsReturned.UpdatedAt = DateTime.Now; auditDetailsReturned.UpdatedBy = command.Username; foreach (var auditChange in auditChanges) { foreach (var fieldChange in auditChange.FieldChanges) { auditDetailsReturned.FieldChanges.Add(fieldChange); } } return(auditDetailsReturned); } return(null); }
private void SetMockAudit() { MockAudit = new Mock <DbSet <Audit> >().SetupData(AuditData.Data()); MockAudit.Setup(x => x.Find(It.IsAny <object[]>())).Returns <object[]>(ids => AuditData.Data().FirstOrDefault(d => d.AuditId == (int)ids[0])); MockAudit.Setup(x => x.FindAsync(It.IsAny <object[]>())).Returns <object[]>(ids => Task.FromResult(AuditData.Data().FirstOrDefault(d => d.AuditId == (int)ids[0]))); MockContext.Setup(x => x.Audit).Returns(MockAudit.Object); }
public AuditData AuditProviderType(Guid organisationId, string updatedBy, int newProviderTypeId, int newOrganisationTypeId) { var auditData = new AuditData { FieldChanges = new List <AuditLogEntry>(), OrganisationId = organisationId, UpdatedAt = DateTime.Now, UpdatedBy = updatedBy }; var previousProviderTypeId = _organisationRepository.GetProviderType(organisationId).Result; var previousOrganisationTypeId = _organisationRepository.GetOrganisationType(organisationId).Result; var previousOrganisationStatusId = _organisationRepository.GetOrganisationStatus(organisationId).Result; var providerTypes = _lookupDataRepository.GetProviderTypes().Result.ToList(); var organisationTypes = _lookupDataRepository.GetOrganisationTypes().Result.ToList(); var organisationStatuses = _lookupDataRepository.GetOrganisationStatuses().Result.ToList(); var previousProviderType = providerTypes.FirstOrDefault(x => x.Id == previousProviderTypeId)?.Type ?? "not defined"; var newProviderType = providerTypes.FirstOrDefault(x => x.Id == newProviderTypeId)?.Type ?? "not defined"; var previousOrganisationType = organisationTypes.FirstOrDefault(x => x.Id == previousOrganisationTypeId)?.Type ?? "not defined"; var newOrganisationType = organisationTypes.FirstOrDefault(x => x.Id == newOrganisationTypeId)?.Type ?? "not defined"; var previousOrganisationStatus = organisationStatuses.FirstOrDefault(x => x.Id == previousOrganisationStatusId)?.Status ?? "not defined"; var activeOrganisationStatus = organisationStatuses.FirstOrDefault(x => x.Id == OrganisationStatus.Active)?.Status ?? "not defined"; var previousStartDate = _organisationRepository.GetStartDate(organisationId).Result; if (previousOrganisationTypeId != newOrganisationTypeId) { var entry = new AuditLogEntry { FieldChanged = AuditLogField.OrganisationType, PreviousValue = previousOrganisationType, NewValue = newOrganisationType }; auditData.FieldChanges.Add(entry); } if (previousProviderTypeId != newProviderTypeId) { var entry = new AuditLogEntry { FieldChanged = AuditLogField.ProviderType, PreviousValue = previousProviderType, NewValue = newProviderType }; auditData.FieldChanges.Add(entry); } var changeStatusToActiveAndSetStartDate = _organisationStatusManager.ShouldChangeStatustoActiveAndSetStartDateToToday(newProviderTypeId, previousProviderTypeId, previousOrganisationStatusId); if (changeStatusToActiveAndSetStartDate) { if (previousOrganisationStatusId != OrganisationStatus.Active) { var entry = new AuditLogEntry { FieldChanged = AuditLogField.OrganisationStatus, PreviousValue = previousOrganisationStatus, NewValue = activeOrganisationStatus }; auditData.FieldChanges.Add(entry); } if (previousStartDate == null || previousStartDate.Value.Date != DateTime.Today.Date) { var entry = new AuditLogEntry { FieldChanged = AuditLogField.StartDate, PreviousValue = previousStartDate?.ToShortDateString() ?? "Not set", NewValue = DateTime.Today.ToShortDateString() }; auditData.FieldChanges.Add(entry); } } return(auditData); }
/// <summary> /// Create a resource /// </summary> public DomainResourceBase CreateResource(string resourceType, string mimeType, DomainResourceBase target) { this.ThrowIfNotReady(); FhirOperationResult result = null; AuditData audit = null; IAuditorService auditService = ApplicationContext.Current.GetService(typeof(IAuditorService)) as IAuditorService; try { // Setup outgoing content // Create or update? var handler = FhirResourceHandlerUtil.GetResourceHandler(resourceType); if (handler == null) { throw new FileNotFoundException(); // endpoint not found! } result = handler.Create(target, TransactionMode.Commit); WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.Created; if (result == null || result.Outcome == ResultCode.Rejected) { throw new InvalidDataException("Resource structure is not valid"); } else if (result.Outcome == ResultCode.AcceptedNonConformant) { throw new ConstraintException("Resource not conformant"); } else if (result.Outcome == ResultCode.TypeNotAvailable) { throw new FileNotFoundException(String.Format("Resource {0} not found", WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri)); } else if (result.Outcome != ResultCode.Accepted) { throw new DataException("Create failed"); } audit = AuditUtil.CreateAuditData(result.Results); String baseUri = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.BaseUri.AbsoluteUri; WebOperationContext.Current.OutgoingResponse.Headers.Add("Content-Location", String.Format("{0}{1}/{2}/_history/{3}", baseUri, resourceType, result.Results[0].Id, result.Results[0].VersionId)); WebOperationContext.Current.OutgoingResponse.LastModified = result.Results[0].Timestamp; WebOperationContext.Current.OutgoingResponse.ETag = result.Results[0].VersionId; return(result.Results[0]); } catch (Exception e) { audit = AuditUtil.CreateAuditData(null); audit.Outcome = OutcomeIndicator.EpicFail; return(this.ErrorHelper(e, result, false) as DomainResourceBase); } finally { if (auditService != null) { auditService.SendAudit(audit); } } }
/// <summary> /// Submits a diagnostic report. /// </summary> /// <param name="report">The diagnostic report.</param> /// <returns>Returns the submitted diagnostic report.</returns> public void SubmitAudit(AuditData report) { this.Client.Post <AuditData, object>("Audit", report); }
/* * protected void Trace (LogController logController, string message) * { * var logInfo = new LogInfo { * LogTypeKey = EventLogController.EventLogType.ADMIN_ALERT.ToString (), * LogUserID = -1, // superuser * LogPortalID = PortalId * }; * * logInfo.AddProperty ("EditNewsEntry", message); * logController.AddLog (logInfo); * } */ protected override void LoadItem(NewsEntryInfo item) { item = (NewsEntryInfo)item.WithContentItem().WithText(); var image = item.ContentItem.Images.FirstOrDefault(); if (image != null) { pickerImage.FileID = image.FileId; } textTitle.Text = item.Title; textDescription.Text = item.Description; txtText.Text = item.Text; datetimeThresholdDate.SelectedDate = item.ThresholdDate; datetimeDueDate.SelectedDate = item.DueDate; datetimeStartDate.SelectedDate = item.StartDate; datetimeEndDate.SelectedDate = item.EndDate; var termSelector = new TermSelector(); termSelector.SelectTerms(selTerms, item.ContentItem.Terms); ctlUrl.Url = item.Url; textPermalinkRaw.Text = item.GetPermalinkRaw(NewsDataProvider.Instance.ModuleController, PortalAlias, ModuleId, TabId); textPermalinkFriendly.Text = item.GetPermalinkFriendly(NewsDataProvider.Instance.ModuleController, ModuleId, TabId); // REVIEW: Check for max value? sliderThematicWeight.Text = item.ThematicWeight.ToString(); sliderStructuralWeight.Text = item.StructuralWeight.ToString(); hiddenDiscussProviderKey.Value = item.DiscussProviderKey; hiddenDiscussEntryId.Value = item.DiscussEntryId; if (!string.IsNullOrEmpty(item.DiscussProviderKey)) { buttonClearDiscussionLink.Visible = IsAdmin(); var discussProvider = NewsConfig.Instance.GetDiscussProviders().FirstOrDefault(dp => dp.ProviderKey == item.DiscussProviderKey); if (discussProvider != null) { textDiscussionLink.Text = discussProvider.GetDiscussUrl(item.DiscussEntryId); } } txtAgentModuleId.Text = item.AgentModuleId.ToString(); var auditData = new AuditData { CreatedDate = item.ContentItem.CreatedOnDate.ToLongDateString(), LastModifiedDate = item.ContentItem.LastModifiedOnDate.ToLongDateString(), }; var createdByUser = item.ContentItem.CreatedByUser(PortalId); auditData.CreatedByUser = (createdByUser != null) ? createdByUser.DisplayName : LocalizeString("SystemUser.Text"); var lastModifiedByUser = item.ContentItem.LastModifiedByUser(PortalId); auditData.LastModifiedByUser = (lastModifiedByUser != null) ? lastModifiedByUser.DisplayName : LocalizeString("SystemUser.Text"); // bind audit control and store data to the viewstate BindAuditControl(auditData); ViewState ["AuditData"] = auditData; buttonUpdate.Text = LocalizeString("Update.Text"); }
/// <summary> /// Convert a db audit to model /// </summary> private AuditData ToModelInstance(SQLiteConnection context, DbAuditData.QueryResult res, bool summary = true) { var retVal = new AuditData() { ActionCode = (ActionType)res.ActionCode, EventIdentifier = (EventIdentifierType)res.EventIdentifier, Outcome = (OutcomeIndicator)res.Outcome, Timestamp = res.Timestamp, CorrelationToken = new Guid(res.Id) }; if (res.EventTypeCode != null) { var concept = ApplicationContext.Current.GetService <IConceptRepositoryService>().GetConcept(res.Code); retVal.EventTypeCode = new AuditCode(res.Code, res.CodeSystem) { DisplayName = concept?.ConceptNames.First()?.Name ?? res.Code }; } // Get actors and objects if (!summary) { // Actors var sql = new SqlStatement <DbAuditActorAssociation>().SelectFrom() .InnerJoin <DbAuditActorAssociation, DbAuditActor>(o => o.TargetUuid, o => o.Id) .Join <DbAuditActor, DbAuditCode>("LEFT", o => o.ActorRoleCode, o => o.Id) .Where <DbAuditActorAssociation>(o => o.SourceUuid == res.Id) .Build(); foreach (var itm in context.Query <DbAuditActor.QueryResult>(sql.SQL, sql.Arguments.ToArray())) { retVal.Actors.Add(new AuditActorData() { UserName = itm.UserName, UserIsRequestor = itm.UserIsRequestor, UserIdentifier = itm.UserIdentifier, ActorRoleCode = new List <AuditCode>() { new AuditCode(itm.Code, itm.CodeSystem) } }); } // Objects foreach (var itm in context.Table <DbAuditObject>().Where(o => o.AuditId == res.Id)) { retVal.AuditableObjects.Add(new AuditableObject() { IDTypeCode = (AuditableObjectIdType?)itm.IDTypeCode, LifecycleType = (AuditableObjectLifecycle?)itm.LifecycleType, NameData = itm.NameData, ObjectId = itm.ObjectId, QueryData = itm.QueryData, Role = (AuditableObjectRole?)itm.Role, Type = (AuditableObjectType)itm.Type }); } } else { // Actors var sql = new SqlStatement <DbAuditActorAssociation>().SelectFrom() .InnerJoin <DbAuditActorAssociation, DbAuditActor>(o => o.TargetUuid, o => o.Id) .Join <DbAuditActor, DbAuditCode>("LEFT", o => o.ActorRoleCode, o => o.Id) .Where <DbAuditActorAssociation>(o => o.SourceUuid == res.Id).And <DbAuditActor>(p => p.UserIsRequestor == true) .Build(); foreach (var itm in context.Query <DbAuditActor.QueryResult>(sql.SQL, sql.Arguments.ToArray())) { retVal.Actors.Add(new AuditActorData() { UserName = itm.UserName, UserIsRequestor = itm.UserIsRequestor, UserIdentifier = itm.UserIdentifier, ActorRoleCode = new List <AuditCode>() { new AuditCode(itm.Code, itm.CodeSystem) } }); } } return(retVal); }