/// <summary> /// Audits the generic error. /// </summary> /// <param name="outcomeIndicator">The outcome indicator.</param> /// <param name="eventTypeCode">The event type code.</param> /// <param name="eventIdentifierType">Type of the event identifier.</param> /// <param name="exception">The exception.</param> public override void AuditGenericError(OutcomeIndicator outcomeIndicator, AuditCode eventTypeCode, EventIdentifierType eventIdentifierType, Exception exception) { var audit = this.CreateBaseAudit(ActionType.Execute, eventTypeCode, eventIdentifierType, outcomeIndicator); audit.AuditableObjects.Add(new AuditableObject { IDTypeCode = AuditableObjectIdType.Uri, ObjectId = this.Context.Request.Url.ToString(), Role = AuditableObjectRole.Resource, Type = AuditableObjectType.SystemObject }); if (exception != null) { var auditableObject = new AuditableObject { IDTypeCode = AuditableObjectIdType.Custom, ObjectId = exception.GetHashCode().ToString(), Role = AuditableObjectRole.Resource, Type = AuditableObjectType.Other }; auditableObject.ObjectData.Add(new ObjectDataExtension(exception.GetType().Name, ObjectToByteArray(new Error(exception)))); audit.AuditableObjects.Add(auditableObject); } AuditService.SendAudit(audit); }
/// <summary> /// Create auditable object /// </summary> private IEnumerable <AuditableObject> CreateAuditObjects(Resource resource, AuditableObjectLifecycle lifecycle) { var obj = new AuditableObject() { ObjectId = $"urn:uuid:{resource.Id}", IDTypeCode = AuditableObjectIdType.Uri, LifecycleType = lifecycle }; if (resource.TryDeriveResourceType(out ResourceType rt)) { switch (rt) { case ResourceType.Patient: obj.Type = AuditableObjectType.Person; obj.Role = AuditableObjectRole.Patient; obj.IDTypeCode = AuditableObjectIdType.PatientNumber; obj.ObjectId = resource.Id; return(new AuditableObject[] { obj }); case ResourceType.Organization: obj.Type = AuditableObjectType.Organization; obj.Role = AuditableObjectRole.Resource; return(new AuditableObject[] { obj }); case ResourceType.Practitioner: obj.Type = AuditableObjectType.Person; obj.Role = AuditableObjectRole.Provider; return(new AuditableObject[] { obj }); case ResourceType.Bundle: return((resource as Bundle).Entry.SelectMany(o => CreateAuditObjects(o.Resource, lifecycle))); default: return(new AuditableObject[0]); } } else { return(new AuditableObject[0]); } }
/// <summary> /// Queue the sending of an audit /// </summary> /// <param name="state"></param> private void SendAuditAsync(object state) { try { var ad = state as MARC.HI.EHRS.SVC.Auditing.Data.AuditData; var configuration = ApplicationContext.Current.Configuration; // Create the audit basic AuditMessage am = new AuditMessage( ad.Timestamp, (ActionType)Enum.Parse(typeof(ActionType), ad.ActionCode.ToString()), (OutcomeIndicator)Enum.Parse(typeof(OutcomeIndicator), ad.Outcome.ToString()), (EventIdentifierType)Enum.Parse(typeof(EventIdentifierType), ad.EventIdentifier.ToString()), null ); if (ad.EventTypeCode != null) { am.EventIdentification.EventType.Add(new CodeValue <String>(ad.EventTypeCode.Code, ad.EventTypeCode.CodeSystem) { DisplayName = ad.EventTypeCode.DisplayName }); } am.SourceIdentification.Add(new AuditSourceIdentificationType() { AuditEnterpriseSiteID = ad.Metadata.FirstOrDefault(o => o.Key == Data.AuditMetadataKey.EnterpriseSiteID)?.Value ?? String.Format("{1}^^^&{0}&ISO", configuration.DeviceIdentifier, configuration.DeviceName), AuditSourceID = ad.Metadata.FirstOrDefault(o => o.Key == Data.AuditMetadataKey.AuditSourceID)?.Value ?? Dns.GetHostName(), AuditSourceTypeCode = new List <CodeValue <AuditSourceType> >() { new CodeValue <AuditSourceType>( (AuditSourceType)Enum.Parse(typeof(AuditSourceType), ad.Metadata.FirstOrDefault(o => o.Key == Data.AuditMetadataKey.AuditSourceType)?.Value ?? "ApplicationServerProcess")) } }); // Add additional data like the participant bool thisFound = false; string dnsName = Dns.GetHostName(); foreach (var adActor in ad.Actors) { thisFound |= (adActor.NetworkAccessPointId == Environment.MachineName || adActor.NetworkAccessPointId == dnsName) && adActor.NetworkAccessPointType == MARC.HI.EHRS.SVC.Auditing.Data.NetworkAccessPointType.MachineName; var act = new AuditActorData() { NetworkAccessPointId = adActor.NetworkAccessPointId, NetworkAccessPointType = (NetworkAccessPointType)Enum.Parse(typeof(NetworkAccessPointType), adActor.NetworkAccessPointType.ToString()), NetworkAccessPointTypeSpecified = adActor.NetworkAccessPointType != 0, UserIdentifier = adActor.UserIdentifier, UserIsRequestor = adActor.UserIsRequestor, UserName = adActor.UserName, AlternativeUserId = adActor.AlternativeUserId }; foreach (var rol in adActor.ActorRoleCode) { act.ActorRoleCode.Add(new CodeValue <string>(rol.Code, rol.CodeSystem) { DisplayName = rol.DisplayName }); } am.Actors.Add(act); } foreach (var aoPtctpt in ad.AuditableObjects) { var atnaAo = new AuditableObject() { IDTypeCode = aoPtctpt.IDTypeCode.HasValue ? aoPtctpt.IDTypeCode.Value != Auditing.Data.AuditableObjectIdType.Custom ? new CodeValue <AuditableObjectIdType>((AuditableObjectIdType)Enum.Parse(typeof(AuditableObjectIdType), aoPtctpt?.IDTypeCode?.ToString())) : (aoPtctpt.CustomIdTypeCode != null ? new CodeValue <AuditableObjectIdType>() { Code = aoPtctpt.CustomIdTypeCode?.Code, CodeSystem = aoPtctpt.CustomIdTypeCode?.CodeSystem, DisplayName = aoPtctpt.CustomIdTypeCode?.DisplayName } : null) : null, LifecycleType = aoPtctpt.LifecycleType.HasValue ? (AuditableObjectLifecycle)Enum.Parse(typeof(AuditableObjectLifecycle), aoPtctpt.LifecycleType.ToString()) : 0, LifecycleTypeSpecified = aoPtctpt.LifecycleType.HasValue, ObjectId = aoPtctpt.ObjectId, Role = aoPtctpt.Role.HasValue ? (AuditableObjectRole)Enum.Parse(typeof(AuditableObjectRole), aoPtctpt.Role.ToString()) : 0, RoleSpecified = aoPtctpt.Role != 0, Type = (AuditableObjectType)Enum.Parse(typeof(AuditableObjectType), aoPtctpt.Type.ToString()), TypeSpecified = aoPtctpt.Type != 0, ObjectSpec = aoPtctpt.QueryData ?? aoPtctpt.NameData, ObjectSpecChoice = aoPtctpt.QueryData == null ? ObjectDataChoiceType.ParticipantObjectName : ObjectDataChoiceType.ParticipantObjectQuery }; // TODO: Object Data foreach (var kv in aoPtctpt.ObjectData) { if (!String.IsNullOrEmpty(kv.Key)) { atnaAo.ObjectDetail.Add(new ObjectDetailType() { Type = kv.Key, Value = kv.Value }); } } am.AuditableObjects.Add(atnaAo); } // Was a record of this service found? if (!thisFound) { am.Actors.Add(new AuditActorData() { NetworkAccessPointId = Environment.MachineName, NetworkAccessPointType = NetworkAccessPointType.MachineName, UserIdentifier = String.Format("{1}^^^&{0}&ISO", configuration.DeviceIdentifier, configuration.DeviceName) }); } // Send the message this.m_configuration.MessagePublisher.SendMessage(am); } catch (Exception e) { Trace.TraceError(e.ToString()); } }
/// <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> /// 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> /// Creates the base audit. /// </summary> /// <param name="actionType">Type of the action.</param> /// <param name="eventTypeCode">The event type code.</param> /// <param name="eventIdentifierType">Type of the event identifier.</param> /// <param name="outcomeIndicator">The outcome indicator.</param> /// <returns>Returns the created base audit data.</returns> protected override AuditData CreateBaseAudit(ActionType actionType, AuditCode eventTypeCode, EventIdentifierType eventIdentifierType, OutcomeIndicator outcomeIndicator) { var audit = base.CreateBaseAudit(actionType, eventTypeCode, eventIdentifierType, outcomeIndicator); var remoteIp = GetLocalIPAddress(); try { // attempt to get the remote IP address remoteIp = this.Context.Request.ServerVariables["REMOTE_ADDR"]; } catch (Exception e) { Trace.TraceError($"Unable to retrieve remote IP address for auditing purposes: {e}"); } var userIdentifier = string.Empty; try { userIdentifier = this.Context.Request.Url.Host; } catch (Exception e) { Trace.TraceError($"Unable to retrieve request host URL for auditing purposes: {e}"); } // add the receiver audit.Actors.Add(new AuditActorData { UserName = Environment.UserName, UserIdentifier = userIdentifier, NetworkAccessPointId = Dns.GetHostName(), NetworkAccessPointType = NetworkAccessPointType.MachineName, AlternativeUserId = Process.GetCurrentProcess().Id.ToString(), ActorRoleCode = new List <AuditCode> { new AuditCode("110152", "DCM") } }); // add the sender audit.Actors.Add(new AuditActorData { UserIdentifier = remoteIp, NetworkAccessPointId = remoteIp, NetworkAccessPointType = NetworkAccessPointType.IPAddress, ActorRoleCode = new List <AuditCode> { new AuditCode("110153", "DCM") }, UserIsRequestor = true }); // add the user if this is an authenticated request if (this.Context.User?.Identity?.IsAuthenticated == true) { audit.Actors.Add(new AuditActorData { UserIdentifier = this.Context.User.Identity.Name, UserIsRequestor = true, NetworkAccessPointId = remoteIp, NetworkAccessPointType = NetworkAccessPointType.IPAddress, ActorRoleCode = new List <AuditCode> { new AuditCode("6", "AuditableObjectRole") } }); } else { // add the anonymous actor if the request isn't authenticated audit.Actors.Add(new AuditActorData { UserIdentifier = "Anonymous", UserIsRequestor = true, NetworkAccessPointId = remoteIp, NetworkAccessPointType = NetworkAccessPointType.IPAddress, ActorRoleCode = new List <AuditCode> { new AuditCode("6", "AuditableObjectRole") } }); } try { if (outcomeIndicator != OutcomeIndicator.Success) { // add the object detail using (var memoryStream = new MemoryStream()) { var detail = new ObjectDataExtension { Key = "HTTPMessage" }; using (var streamWriter = new StreamWriter(memoryStream, Encoding.UTF8)) { streamWriter.WriteLine("<?xml version=\"1.0\"?><Request><![CDATA["); streamWriter.WriteLine("{0} {1} HTTP/1.1", this.Context.Request.HttpMethod, this.Context.Request.Url); for (var i = 0; i < this.Context.Request.Headers.Keys.Count; i++) { streamWriter.WriteLine("{0} : {1}", this.Context.Request.Headers.Keys[i], this.Context.Request.Headers[i]); } // Only output if request is not sensitive if (!this.IsRequestSensitive) { using (var sr = new StreamReader(this.Context.Request.InputStream)) { streamWriter.WriteLine("\r\n{0}", sr.ReadToEnd()); } } else { streamWriter.WriteLine("*********** SENSITIVE REQUEST REDACTED ***********"); } streamWriter.WriteLine("]]></Request>"); streamWriter.Flush(); detail.Value = memoryStream.GetBuffer().Take((int)memoryStream.Length).ToArray(); } var auditableObject = new AuditableObject { IDTypeCode = AuditableObjectIdType.Uri, ObjectId = this.Context.Request.Url.ToString(), Role = AuditableObjectRole.Query, Type = AuditableObjectType.SystemObject }; auditableObject.ObjectData.Add(detail); audit.AuditableObjects.Add(auditableObject); } } } catch (Exception e) { Trace.TraceError($"Unable to add object detail to audit message: {e}"); } return(audit); }
/// <summary> /// Convert a db audit to model /// </summary> private AuditData ToModelInstance(DataContext context, CompositeResult <DbAuditData, DbAuditCode> res, bool summary = true) { var retVal = this.m_dataCachingService.GetCacheItem <AuditData>(res.Object1.Key); if (retVal == null || !summary && retVal.LoadState < Core.Model.LoadState.FullLoad) { retVal = new AuditData() { ActionCode = (ActionType)res.Object1.ActionCode, EventIdentifier = (EventIdentifierType)res.Object1.EventIdentifier, Outcome = (OutcomeIndicator)res.Object1.Outcome, Timestamp = res.Object1.Timestamp, Key = res.Object1.Key }; if (res.Object1.EventTypeCode != null) { retVal.EventTypeCode = this.ResolveCode(res.Object1.EventTypeCode, res.Object2.Code, res.Object2.CodeSystem); } // Get actors and objects if (!summary) { // Actors var sql = context.CreateSqlStatement <DbAuditActorAssociation>().SelectFrom(typeof(DbAuditActorAssociation), typeof(DbAuditActor), typeof(DbAuditCode)) .InnerJoin <DbAuditActorAssociation, DbAuditActor>(o => o.TargetKey, o => o.Key) .Join <DbAuditActor, DbAuditCode>("LEFT", o => o.ActorRoleCode, o => o.Key) .Where <DbAuditActorAssociation>(o => o.SourceKey == res.Object1.Key) .Build(); foreach (var itm in context.Query <CompositeResult <DbAuditActorAssociation, DbAuditActor, DbAuditCode> >(sql)) { retVal.Actors.Add(new AuditActorData() { UserName = itm.Object2.UserName, UserIsRequestor = itm.Object1.UserIsRequestor, UserIdentifier = itm.Object2.UserIdentifier, NetworkAccessPointId = itm.Object1.AccessPoint, ActorRoleCode = new List <AuditCode>() { this.ResolveCode(itm.Object2.ActorRoleCode, itm.Object3.Code, itm.Object3.CodeSystem) }.OfType <AuditCode>().ToList() }); } // Objects sql = context.CreateSqlStatement <DbAuditObject>().SelectFrom(typeof(DbAuditObject), typeof(DbAuditCode)) .Join <DbAuditObject, DbAuditCode>("LEFT", o => o.CustomIdType, o => o.Key) .Where <DbAuditObject>(o => o.AuditId == res.Object1.Key); foreach (var itm in context.Query <CompositeResult <DbAuditObject, DbAuditCode> >(sql).ToArray()) { var ao = new AuditableObject() { IDTypeCode = (AuditableObjectIdType?)itm.Object1.IDTypeCode, LifecycleType = (AuditableObjectLifecycle?)itm.Object1.LifecycleType, NameData = itm.Object1.NameData, ObjectId = itm.Object1.ObjectId, QueryData = itm.Object1.QueryData, Role = (AuditableObjectRole?)itm.Object1.Role, Type = (AuditableObjectType)itm.Object1.Type }; if (itm.Object1.CustomIdType.HasValue) { ao.CustomIdTypeCode = new AuditCode(itm.Object2.Code, itm.Object2.CodeSystem); } retVal.AuditableObjects.Add(ao); foreach (var dat in context.Query <DbAuditObjectData>(o => o.ObjectId == itm.Object1.Key)) { ao.ObjectData.Add(new ObjectDataExtension(dat.Name, dat.Value)); } } // Metadata var stmt = context.CreateSqlStatement().SelectFrom(typeof(DbAuditMetadata)) .InnerJoin <DbAuditMetadata, DbAuditMetadataValue>(o => o.ValueId, o => o.Key) .Where <DbAuditMetadata>(o => o.AuditId == res.Object1.Key); foreach (var itm in context.Query <CompositeResult <DbAuditMetadata, DbAuditMetadataValue> >(stmt)) { retVal.AddMetadata((AuditMetadataKey)itm.Object1.MetadataKey, itm.Object2.Value); } retVal.LoadState = Core.Model.LoadState.FullLoad; } else { // Actors // Actors var sql = context.CreateSqlStatement <DbAuditActorAssociation>().SelectFrom(typeof(DbAuditActorAssociation), typeof(DbAuditActor), typeof(DbAuditCode)) .InnerJoin <DbAuditActorAssociation, DbAuditActor>(o => o.TargetKey, o => o.Key) .Join <DbAuditActor, DbAuditCode>("LEFT", o => o.ActorRoleCode, o => o.Key) .Where <DbAuditActorAssociation>(o => o.SourceKey == res.Object1.Key) .Build(); foreach (var itm in context.Query <CompositeResult <DbAuditActorAssociation, DbAuditActor, DbAuditCode> >(sql)) { retVal.Actors.Add(new AuditActorData() { UserName = itm.Object2.UserName, UserIsRequestor = itm.Object1.UserIsRequestor, UserIdentifier = itm.Object2.UserIdentifier, NetworkAccessPointId = itm.Object1.AccessPoint, ActorRoleCode = new List <AuditCode>() { this.ResolveCode(itm.Object2.ActorRoleCode, itm.Object3.Code, itm.Object3.CodeSystem) }.OfType <AuditCode>().ToList() }); } retVal.LoadState = Core.Model.LoadState.PartialLoad; } this.m_dataCachingService.Add(retVal); } return(retVal); }
/// <summary> /// Create audit data /// </summary> public static AuditData CreateAuditData(IEnumerable <DomainResourceBase> records) { // Audit data AuditData retVal = null; AuditableObjectLifecycle lifecycle = AuditableObjectLifecycle.Access; // Get the actor information string userId = String.Empty; if (OperationContext.Current.Channel.RemoteAddress != null && OperationContext.Current.Channel.RemoteAddress.Uri != null) { userId = OperationContext.Current.Channel.RemoteAddress.Uri.OriginalString; } else if (OperationContext.Current.ServiceSecurityContext != null && OperationContext.Current.ServiceSecurityContext.PrimaryIdentity != null) { userId = OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name; } MessageProperties properties = OperationContext.Current.IncomingMessageProperties; RemoteEndpointMessageProperty endpoint = properties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty; string remoteEndpoint = "http://anonymous"; if (endpoint != null) { remoteEndpoint = endpoint.Address; } CodeValue itiNameMap = null; if (records == null || records.FirstOrDefault() == null && !s_configuration.ActionMap.TryGetValue(String.Format("{0} ", WebOperationContext.Current.IncomingRequest.Method), out itiNameMap) || records.FirstOrDefault() != null && !s_configuration.ActionMap.TryGetValue(String.Format("{0} {1}", WebOperationContext.Current.IncomingRequest.Method, records.FirstOrDefault().GetType().Name), out itiNameMap)) { itiNameMap = new CodeValue( WebOperationContext.Current.IncomingRequest.Method, "urn:ietf:rfc:2616" ) { DisplayName = WebOperationContext.Current.IncomingRequest.Method } } ; // TODO: Clean this up switch (WebOperationContext.Current.IncomingRequest.Method) { case "GET": { retVal = new AuditData(DateTime.Now, ActionType.Execute, OutcomeIndicator.Success, EventIdentifierType.Query, AuditUtil.CopyCode(itiNameMap)); // Audit actor for Patient Identity Source retVal.Actors.Add(new AuditActorData() { UserIsRequestor = true, UserIdentifier = userId, ActorRoleCode = new List <AuditCode>() { new AuditCode("110153", "DCM") { DisplayName = "Source" } }, NetworkAccessPointId = remoteEndpoint, NetworkAccessPointType = NetworkAccessPointType.IPAddress, UserName = userId }); // Audit actor for FHIR service retVal.Actors.Add(new AuditActorData() { UserIdentifier = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.BaseUri.ToString(), UserIsRequestor = false, ActorRoleCode = new List <AuditCode>() { new AuditCode("110152", "DCM") { DisplayName = "Destination" } }, NetworkAccessPointType = NetworkAccessPointType.MachineName, NetworkAccessPointId = Dns.GetHostName(), UserName = Environment.UserName }); // Serialize the query retVal.AuditableObjects.Add(new AuditableObject() { Type = AuditableObjectType.SystemObject, Role = AuditableObjectRole.Query, IDTypeCode = AuditableObjectIdType.Custom, CustomIdTypeCode = AuditUtil.CopyCode(itiNameMap), ObjectId = itiNameMap.DisplayName.Replace(" ", ""), QueryData = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri.Query)), ObjectData = new List <ObjectDataExtension>() { new ObjectDataExtension(String.Empty, WebOperationContext.Current.IncomingRequest.Headers.ToByteArray()) } }); break; } case "POST": { retVal = new AuditData(DateTime.Now, ActionType.Create, OutcomeIndicator.Success, EventIdentifierType.Import, AuditUtil.CopyCode(itiNameMap)); // Audit actor for Patient Identity Source retVal.Actors.Add(new AuditActorData() { UserIsRequestor = true, UserIdentifier = userId, ActorRoleCode = new List <AuditCode>() { new AuditCode("110153", "DCM") { DisplayName = "Source" } }, NetworkAccessPointId = remoteEndpoint, NetworkAccessPointType = NetworkAccessPointType.IPAddress, UserName = userId }); // Audit actor for FHIR service retVal.Actors.Add(new AuditActorData() { UserIdentifier = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.BaseUri.ToString(), UserIsRequestor = false, ActorRoleCode = new List <AuditCode>() { new AuditCode("110152", "DCM") { DisplayName = "Destination" } }, NetworkAccessPointType = NetworkAccessPointType.MachineName, NetworkAccessPointId = Dns.GetHostName(), UserName = Environment.UserName }); break; } case "PUT": { retVal = new AuditData(DateTime.Now, ActionType.Update, OutcomeIndicator.Success, EventIdentifierType.Import, AuditUtil.CopyCode(itiNameMap)); // Audit actor for Patient Identity Source retVal.Actors.Add(new AuditActorData() { UserIsRequestor = true, UserIdentifier = userId, ActorRoleCode = new List <AuditCode>() { new AuditCode("110153", "DCM") { DisplayName = "Source" } }, NetworkAccessPointId = remoteEndpoint, NetworkAccessPointType = NetworkAccessPointType.IPAddress, UserName = userId }); // Audit actor for FHIR service retVal.Actors.Add(new AuditActorData() { UserIdentifier = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.BaseUri.ToString(), UserIsRequestor = false, ActorRoleCode = new List <AuditCode>() { new AuditCode("110152", "DCM") { DisplayName = "Destination" } }, NetworkAccessPointType = NetworkAccessPointType.MachineName, NetworkAccessPointId = Dns.GetHostName(), UserName = Environment.UserName }); break; } case "DELETE": { retVal = new AuditData(DateTime.Now, ActionType.Delete, OutcomeIndicator.Success, EventIdentifierType.Import, AuditUtil.CopyCode(itiNameMap)); // Audit actor for Patient Identity Source retVal.Actors.Add(new AuditActorData() { UserIsRequestor = true, UserIdentifier = userId, ActorRoleCode = new List <AuditCode>() { new AuditCode("110153", "DCM") { DisplayName = "Source" } }, NetworkAccessPointId = remoteEndpoint, NetworkAccessPointType = NetworkAccessPointType.IPAddress, UserName = userId }); // Audit actor for FHIR service retVal.Actors.Add(new AuditActorData() { UserIdentifier = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.BaseUri.ToString(), UserIsRequestor = false, ActorRoleCode = new List <AuditCode>() { new AuditCode("110152", "DCM") { DisplayName = "Destination" } }, NetworkAccessPointType = NetworkAccessPointType.MachineName, NetworkAccessPointId = Dns.GetHostName(), UserName = Environment.UserName }); break; } default: { retVal = new AuditData(DateTime.Now, ActionType.Execute, OutcomeIndicator.Success, EventIdentifierType.ApplicationActivity, new AuditCode( String.Format("GET {0}", WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri.OriginalString), "http://marc-hi.ca/fhir/actions")); break; } } if (records != null) { foreach (DomainResourceBase pat in records) { // TODO: Make this more generic AuditableObject aud = null; var ptcptObjMap = pat.GetType().GetCustomAttributes(typeof(ParticipantObjectMapAttribute), true); string domain = String.Empty; if (ptcptObjMap.Length > 0) { var mapAttribute = ptcptObjMap[0] as ParticipantObjectMapAttribute; domain = ApplicationContext.Current.GetService <IOidRegistrarService>()?.GetOid(mapAttribute.OidName)?.Oid; aud = new AuditableObject() { IDTypeCode = mapAttribute.IdType, Role = mapAttribute.Role, Type = mapAttribute.Type }; } else { continue; } // Lifecycle switch (retVal.ActionCode) { 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.ObjectId = String.Format("{1}^^^&{0}&ISO", domain, pat.Id); retVal.AuditableObjects.Add(aud); } } return(retVal); }
/// <summary> /// Create audit data /// </summary> public AuditData CreateAuditData(string itiName, ActionType action, OutcomeIndicator outcome, UnsolicitedDataEventArgs msgEvent, IReceiveResult msgReceiveResult, IEnumerable <VersionedDomainIdentifier> patientRecord, HealthcareParticipant author) { // Audit data AuditData retVal = null; AuditableObjectLifecycle lifecycle = AuditableObjectLifecycle.Access; var wcfReceiveResult = msgReceiveResult as WcfReceiveResult; var msgReplyTo = wcfReceiveResult == null || wcfReceiveResult.Headers == null || wcfReceiveResult.Headers.ReplyTo == null?msgEvent.SolicitorEndpoint.ToString() : wcfReceiveResult.Headers.ReplyTo.Uri.ToString(); string userId = String.Empty; if (OperationContext.Current.Channel.RemoteAddress != null && OperationContext.Current.Channel.RemoteAddress.Uri != null) { userId = OperationContext.Current.Channel.RemoteAddress.Uri.OriginalString; } else if (OperationContext.Current.ServiceSecurityContext != null && OperationContext.Current.ServiceSecurityContext.PrimaryIdentity != null) { userId = OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name; } switch (itiName) { case "PRPA_TE101103CA": { retVal = new AuditData(DateTime.Now, action, outcome, EventIdentifierType.PatientRecord, new CodeValue(itiName, "HL7 Trigger Events")); // Audit actor for Patient Identity Source retVal.Actors.Add(new AuditActorData() { UserIsRequestor = true, UserIdentifier = msgReplyTo, ActorRoleCode = new List <CodeValue>() { new CodeValue("110153", "DCM") { DisplayName = "Source" } }, NetworkAccessPointId = msgEvent.SolicitorEndpoint.Host, NetworkAccessPointType = msgEvent.SolicitorEndpoint.HostNameType == UriHostNameType.Dns ? NetworkAccessPointType.MachineName : NetworkAccessPointType.IPAddress, UserName = userId }); // Audit actor for PIX manager retVal.Actors.Add(new AuditActorData() { UserIdentifier = msgEvent.ReceiveEndpoint.ToString(), UserIsRequestor = false, ActorRoleCode = new List <CodeValue>() { new CodeValue("110152", "DCM") { DisplayName = "Destination" } }, NetworkAccessPointType = NetworkAccessPointType.MachineName, NetworkAccessPointId = Dns.GetHostName(), AlternativeUserId = Process.GetCurrentProcess().Id.ToString() }); var request = msgReceiveResult.Structure as MARC.Everest.RMIM.CA.R020403.Interactions.PRPA_IN101103CA; retVal.AuditableObjects.Add(new AuditableObject() { Type = AuditableObjectType.SystemObject, Role = AuditableObjectRole.Query, IDTypeCode = AuditableObjectIdType.SearchCritereon, QueryData = Convert.ToBase64String(SerializeQuery(request.controlActEvent.QueryByParameter)), ObjectId = String.Format("{1}^^^&{0}&ISO", request.controlActEvent.QueryByParameter.QueryId.Root, request.controlActEvent.QueryByParameter.QueryId.Extension) }); break; } case "PRPA_TE101101CA": { retVal = new AuditData(DateTime.Now, action, outcome, EventIdentifierType.PatientRecord, new CodeValue(itiName, "HL7 Trigger Events")); // Audit actor for Patient Identity Source retVal.Actors.Add(new AuditActorData() { UserIsRequestor = true, UserIdentifier = msgReplyTo, ActorRoleCode = new List <CodeValue>() { new CodeValue("110153", "DCM") { DisplayName = "Source" } }, NetworkAccessPointId = msgEvent.SolicitorEndpoint.Host, NetworkAccessPointType = msgEvent.SolicitorEndpoint.HostNameType == UriHostNameType.Dns ? NetworkAccessPointType.MachineName : NetworkAccessPointType.IPAddress, UserName = userId }); // Audit actor for PIX manager retVal.Actors.Add(new AuditActorData() { UserIdentifier = msgEvent.ReceiveEndpoint.ToString(), UserIsRequestor = false, ActorRoleCode = new List <CodeValue>() { new CodeValue("110152", "DCM") { DisplayName = "Destination" } }, NetworkAccessPointType = NetworkAccessPointType.MachineName, NetworkAccessPointId = Dns.GetHostName(), AlternativeUserId = Process.GetCurrentProcess().Id.ToString() }); var request = msgReceiveResult.Structure as MARC.Everest.RMIM.CA.R020403.Interactions.PRPA_IN101101CA; retVal.AuditableObjects.Add(new AuditableObject() { Type = AuditableObjectType.SystemObject, Role = AuditableObjectRole.Query, IDTypeCode = AuditableObjectIdType.SearchCritereon, QueryData = Convert.ToBase64String(SerializeQuery(request.controlActEvent.QueryByParameter)), ObjectId = String.Format("{1}^^^&{0}&ISO", request.controlActEvent.QueryByParameter.QueryId.Root, request.controlActEvent.QueryByParameter.QueryId.Extension) }); break; } case "PRPA_TE101201CA": { retVal = new AuditData(DateTime.Now, action, outcome, EventIdentifierType.PatientRecord, new CodeValue(itiName, "HL7 Trigger Events")); // Audit actor for Patient Identity Source retVal.Actors.Add(new AuditActorData() { UserIsRequestor = true, UserIdentifier = msgReplyTo, ActorRoleCode = new List <CodeValue>() { new CodeValue("110153", "DCM") { DisplayName = "Source" } }, NetworkAccessPointId = msgEvent.SolicitorEndpoint.Host, NetworkAccessPointType = msgEvent.SolicitorEndpoint.HostNameType == UriHostNameType.Dns ? NetworkAccessPointType.MachineName : NetworkAccessPointType.IPAddress, UserName = userId }); // Audit actor for PIX manager retVal.Actors.Add(new AuditActorData() { UserIdentifier = msgEvent.ReceiveEndpoint.ToString(), 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 "PRPA_TE101105CA": { retVal = new AuditData(DateTime.Now, action, outcome, EventIdentifierType.PatientRecord, new CodeValue(itiName, "HL7 Trigger Events")); // Audit actor for Patient Identity Source retVal.Actors.Add(new AuditActorData() { UserIsRequestor = true, UserIdentifier = msgReplyTo, ActorRoleCode = new List <CodeValue>() { new CodeValue("110153", "DCM") { DisplayName = "Source" } }, NetworkAccessPointId = msgEvent.SolicitorEndpoint.Host, NetworkAccessPointType = msgEvent.SolicitorEndpoint.HostNameType == UriHostNameType.Dns ? NetworkAccessPointType.MachineName : NetworkAccessPointType.IPAddress, UserName = userId }); // Audit actor for PIX manager retVal.Actors.Add(new AuditActorData() { UserIdentifier = msgEvent.ReceiveEndpoint.ToString(), UserIsRequestor = false, ActorRoleCode = new List <CodeValue>() { new CodeValue("110152", "DCM") { DisplayName = "Destination" } }, NetworkAccessPointType = NetworkAccessPointType.MachineName, NetworkAccessPointId = Dns.GetHostName(), AlternativeUserId = Process.GetCurrentProcess().Id.ToString() }); var request = msgReceiveResult.Structure as MARC.Everest.RMIM.CA.R020403.Interactions.PRPA_IN101105CA; retVal.AuditableObjects.Add(new AuditableObject() { Type = AuditableObjectType.SystemObject, Role = AuditableObjectRole.Query, IDTypeCode = AuditableObjectIdType.SearchCritereon, QueryData = Convert.ToBase64String(SerializeQuery(request.controlActEvent.QueryByParameter)), ObjectId = String.Format("{1}^^^&{0}&ISO", request.controlActEvent.QueryByParameter.QueryId.Root, request.controlActEvent.QueryByParameter.QueryId.Extension) }); break; break; } case "ITI-44": retVal = new AuditData(DateTime.Now, action, outcome, EventIdentifierType.PatientRecord, new CodeValue(itiName, "IHE Transactions")); // Audit actor for Patient Identity Source retVal.Actors.Add(new AuditActorData() { UserIsRequestor = true, UserIdentifier = msgReplyTo, ActorRoleCode = new List <CodeValue>() { new CodeValue("110153", "DCM") { DisplayName = "Source" } }, NetworkAccessPointId = msgEvent.SolicitorEndpoint.Host, NetworkAccessPointType = msgEvent.SolicitorEndpoint.HostNameType == UriHostNameType.Dns ? NetworkAccessPointType.MachineName : NetworkAccessPointType.IPAddress, UserName = userId }); // Audit actor for PIX manager retVal.Actors.Add(new AuditActorData() { UserIdentifier = msgEvent.ReceiveEndpoint.ToString(), 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-45": { retVal = new AuditData(DateTime.Now, ActionType.Execute, outcome, EventIdentifierType.Query, new CodeValue("ITI-45", "IHE Transactions") { DisplayName = "PIX Query" }); // Audit actor for Patient Identity Source retVal.Actors.Add(new AuditActorData() { UserIsRequestor = true, UserIdentifier = msgReplyTo, ActorRoleCode = new List <CodeValue>() { new CodeValue("110153", "DCM") { DisplayName = "Source" } }, NetworkAccessPointId = msgEvent.SolicitorEndpoint.Host, NetworkAccessPointType = msgEvent.SolicitorEndpoint.HostNameType == UriHostNameType.Dns ? NetworkAccessPointType.MachineName : NetworkAccessPointType.IPAddress, UserName = userId }); // Audit actor for PIX manager retVal.Actors.Add(new AuditActorData() { UserIdentifier = msgEvent.ReceiveEndpoint.ToString(), UserIsRequestor = false, ActorRoleCode = new List <CodeValue>() { new CodeValue("110152", "DCM") { DisplayName = "Destination" } }, NetworkAccessPointType = NetworkAccessPointType.MachineName, NetworkAccessPointId = Dns.GetHostName(), AlternativeUserId = Process.GetCurrentProcess().Id.ToString() }); // Add query var request = msgReceiveResult.Structure as PRPA_IN201309UV02; retVal.AuditableObjects.Add(new AuditableObject() { Type = AuditableObjectType.SystemObject, Role = AuditableObjectRole.Query, IDTypeCode = AuditableObjectIdType.Custom, CustomIdTypeCode = new CodeValue("ITI45", "IHE Transactions"), QueryData = Convert.ToBase64String(SerializeQuery(request.controlActProcess.queryByParameter)), ObjectId = String.Format("{1}^^^&{0}&ISO", request.controlActProcess.queryByParameter.QueryId.Root, request.controlActProcess.queryByParameter.QueryId.Extension) }); break; } case "ITI-47": { retVal = new AuditData(DateTime.Now, ActionType.Execute, outcome, EventIdentifierType.Query, new CodeValue("ITI-47", "IHE Transactions") { DisplayName = "Patient Demographics Query" }); // Audit actor for Patient Identity Source retVal.Actors.Add(new AuditActorData() { UserIsRequestor = true, UserIdentifier = msgReplyTo, ActorRoleCode = new List <CodeValue>() { new CodeValue("110153", "DCM") { DisplayName = "Source" } }, NetworkAccessPointId = msgEvent.SolicitorEndpoint.Host, NetworkAccessPointType = msgEvent.SolicitorEndpoint.HostNameType == UriHostNameType.Dns ? NetworkAccessPointType.MachineName : NetworkAccessPointType.IPAddress, UserName = userId }); // Audit actor for PIX manager retVal.Actors.Add(new AuditActorData() { UserIdentifier = msgEvent.ReceiveEndpoint.ToString(), UserIsRequestor = false, ActorRoleCode = new List <CodeValue>() { new CodeValue("110152", "DCM") { DisplayName = "Destination" } }, NetworkAccessPointType = NetworkAccessPointType.MachineName, NetworkAccessPointId = Dns.GetHostName(), AlternativeUserId = Process.GetCurrentProcess().Id.ToString() }); // Add query var request = msgReceiveResult.Structure as PRPA_IN201305UV02; retVal.AuditableObjects.Add(new AuditableObject() { Type = AuditableObjectType.SystemObject, Role = AuditableObjectRole.Query, IDTypeCode = AuditableObjectIdType.Custom, CustomIdTypeCode = new CodeValue("ITI47", "IHE Transactions"), QueryData = Convert.ToBase64String(SerializeQuery(request.controlActProcess.queryByParameter)), ObjectId = String.Format("{1}^^^&{0}&ISO", request.controlActProcess.queryByParameter.QueryId.Root, request.controlActProcess.queryByParameter.QueryId.Extension) }); break; } } // Audit authors if (author != null) { retVal.AuditableObjects.Add(new AuditableObject() { IDTypeCode = AuditableObjectIdType.UserIdentifier, ObjectId = String.Format("{1}^^^&{0}&ISO", this.m_configService.OidRegistrar.GetOid("CR_PID"), author.Id), Role = AuditableObjectRole.Provider, Type = AuditableObjectType.Person, LifecycleType = (AuditableObjectLifecycle?)(action == ActionType.Read ? (object)AuditableObjectLifecycle.ReceiptOfDisclosure : null) }); } // Audit patients foreach (var pat in patientRecord) { // 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.ObjectId = String.Format("{1}^^^&{0}&ISO", pat.Domain, pat.Identifier); retVal.AuditableObjects.Add(aud); } return(retVal); }