/// <summary>
 /// Redirect persistence event
 /// </summary>
 private void OnPrePersistenceEvent(object sender, DataPersistingEventArgs <T> e)
 {
     if (e.Data is Bundle bundle)
     {
         foreach (var itm in bundle.Item.ToArray())
         {
             var masterRel = this.GetMasterRedirect(itm.Key, itm.GetType());
             if (masterRel != null)
             {
                 if (itm is Entity entity) // Add the MDM rel back so it can be saved
                 {
                     entity.Relationships.Add(masterRel as EntityRelationship);
                 }
             }
         }
     }
     else if (e.Data.Key.HasValue) // update/insert
     {
         var masterRel = this.GetMasterRedirect(e.Data.Key);
         if (masterRel != null)           // has a master, so update that instead
         {
             if (e.Data is Entity entity) // Add the MDM rel back so it can be saved
             {
                 entity.Relationships.Add(masterRel as EntityRelationship);
             }
         }
     }
 }
        /// <summary>
        /// Performs insert of object
        /// </summary>
        public virtual TEntity Insert(TEntity data)
        {
            // Demand permission
            this.DemandWrite(data);

            var persistenceService = ApplicationContext.Current.GetService <IDataPersistenceService <TEntity> >();

            if (persistenceService == null)
            {
                throw new InvalidOperationException($"Unable to locate {nameof(IDataPersistenceService<TEntity>)}");
            }

            var preEvent = new DataPersistingEventArgs <TEntity>(data, TransactionMode.Commit, AuthenticationContext.Current.Principal);

            this.Inserting?.Invoke(this, preEvent);
            if (preEvent.Cancel)
            {
                this.m_traceSource.TraceWarning("Pre-persistence event indicates cancel");
                return(preEvent.Data);
            }
            data = preEvent.Data;

            data = this.Validate(data);

            var businessRulesService = ApplicationContext.Current.GetService <IBusinessRulesService <TEntity> >();

            data = businessRulesService?.BeforeInsert(data) ?? data;
            data = persistenceService.Insert(data, TransactionMode.Commit, AuthenticationContext.Current.Principal);
            ApplicationContext.Current.GetService <IQueueManagerService>()?.Outbound.Enqueue(data, SynchronizationOperationType.Insert);
            data = businessRulesService?.AfterInsert(data) ?? data;
            this.Inserted?.Invoke(this, new DataPersistedEventArgs <TEntity>(data, TransactionMode.Commit, AuthenticationContext.Current.Principal));
            return(data);
        }
Esempio n. 3
0
        /// <summary>
        /// Performs insert of object
        /// </summary>
        public virtual TEntity Insert(TEntity data)
        {
            // Demand permission
            this.DemandWrite(data);

            // Validate the resource
            data = this.Validate(data);

            // Fire pre-persistence triggers
            var prePersistence = new DataPersistingEventArgs <TEntity>(data, AuthenticationContext.Current.Principal);

            this.Inserting?.Invoke(this, prePersistence);
            if (prePersistence.Cancel)
            {
                this.m_traceSource.TraceWarning("Pre-persistence event signal cancel: {0}", data);
                return(prePersistence.Data);
            }
            // Did the pre-persistence service change the type to a batch
            var businessRulesService = ApplicationServiceContext.Current.GetBusinessRulesService <TEntity>();
            var persistenceService   = ApplicationServiceContext.Current.GetService <IDataPersistenceService <TEntity> >();

            data = businessRulesService?.BeforeInsert(data) ?? prePersistence.Data;
            data = persistenceService.Insert(data, TransactionMode.Commit, AuthenticationContext.Current.Principal);
            businessRulesService?.AfterInsert(data);
            this.Inserted?.Invoke(this, new DataPersistedEventArgs <TEntity>(data, AuthenticationContext.Current.Principal));

            return(data);
        }
        /// <summary>
        /// Inserts the specified storage data.
        /// </summary>
        /// <param name="storageData">The storage data.</param>
        /// <param name="overrideAuthContext">The principal to use instead of the default.</param>
        /// <param name="mode">The mode.</param>
        /// <returns>Returns the inserted model instance.</returns>
        public TModel Insert(TModel storageData, TransactionMode mode, IPrincipal overrideAuthContext = null)
        {
            if (storageData == null)
            {
                throw new ArgumentNullException(nameof(storageData), "Value cannot be null");
            }

            var preInsertArgs = new DataPersistingEventArgs <TModel>(storageData, overrideAuthContext);

            this.Inserting?.Invoke(this, preInsertArgs);

            if (preInsertArgs.Cancel)
            {
                traceSource.TraceEvent(EventLevel.Warning, $"Pre-event handler indicates abort insert for : {storageData}");
                return(storageData);
            }

            using (var connection = Configuration.Provider.GetWriteConnection())
            {
                connection.Open();

                using (var transaction = connection.BeginTransaction())
                {
                    try
                    {
                        var existing = this.Get(connection, storageData.Key.Value, false, overrideAuthContext);

                        if (existing != null)
                        {
                            throw new DuplicateNameException(storageData.Key?.ToString());
                        }
                        else
                        {
                            this.traceSource.TraceEvent(EventLevel.Verbose, "INSERT {0}", storageData);
                            storageData = this.Insert(connection, storageData);
                        }

                        if (mode == TransactionMode.Commit)
                        {
                            transaction.Commit();
                        }
                        else
                        {
                            transaction.Rollback();
                        }

                        this.Inserted?.Invoke(this, new DataPersistedEventArgs <TModel>(storageData, overrideAuthContext));

                        return(storageData);
                    }
                    catch (Exception e)
                    {
                        this.traceSource.TraceEvent(EventLevel.Error, "Error : {0}", e);
                        transaction?.Rollback();
                        throw new DataPersistenceException(e.Message, e);
                    }
                }
            }
        }
Esempio n. 5
0
 /// <summary>
 /// Represents the bundle operation
 /// </summary>
 protected void AdtPatientRegistrationInterceptor_Bundle(object sender, DataPersistingEventArgs <Bundle> e)
 {
     foreach (var itm in e.Data.Item.OfType <Patient>())
     {
         AdtPatientRegistrationInterceptor_Behavior(sender, new DataPersistingEventArgs <Patient>(itm, e.Principal));
     }
     e.Cancel = true;
 }
        /// <summary>
        /// Obsoletes the specified storage data.
        /// </summary>
        /// <param name="storageData">The storage data.</param>
        /// <param name="overrideAuthContext">The principal to use instead of the default.</param>
        /// <param name="mode">The mode.</param>
        /// <returns>TModel.</returns>
        public TModel Obsolete(TModel storageData, TransactionMode mode, IPrincipal overrideAuthContext = null)
        {
            if (storageData == null)
            {
                throw new ArgumentNullException(nameof(storageData), "Value cannot be null");
            }

            if (!storageData.Key.HasValue || storageData.Key == Guid.Empty)
            {
                throw new InvalidOperationException("Data missing key");
            }

            var prePersistenceEventArgs = new DataPersistingEventArgs <TModel>(storageData, overrideAuthContext);

            this.Obsoleting?.Invoke(this, prePersistenceEventArgs);

            if (prePersistenceEventArgs.Cancel)
            {
                traceSource.TraceEvent(EventLevel.Warning, $"Pre-event handler indicates abort for {storageData}");
                return(storageData);
            }

            using (var connection = Configuration.Provider.GetWriteConnection())
            {
                connection.Open();

                using (var transaction = connection.BeginTransaction())
                {
                    try
                    {
                        this.traceSource.TraceEvent(EventLevel.Verbose, $"OBSOLETE {storageData}");

                        storageData = this.Obsolete(connection, storageData);

                        if (mode == TransactionMode.Commit)
                        {
                            transaction.Commit();
                        }
                        else
                        {
                            transaction.Rollback();
                        }

                        var args = new DataPersistedEventArgs <TModel>(storageData, overrideAuthContext);

                        this.Obsoleted?.Invoke(this, args);

                        return(storageData);
                    }
                    catch (Exception e)
                    {
                        traceSource.TraceEvent(EventLevel.Error, $"Error obsoleting: {storageData}");
                        transaction.Rollback();
                        throw new DataPersistenceException(e.Message, e);
                    }
                }
            }
        }
Esempio n. 7
0
        public DiagnosticReport Insert(DiagnosticReport storageData, TransactionMode mode, IPrincipal overrideAuthContext = null)
        {
            var persistenceArgs = new DataPersistingEventArgs <DiagnosticReport>(storageData, mode, overrideAuthContext);

            this.Inserting?.Invoke(this, persistenceArgs);
            if (persistenceArgs.Cancel)
            {
                this.m_traceSource.TraceEvent(EventLevel.Warning, "Pre-persistence event cancelled the insertion");
                return(persistenceArgs.Data);
            }

            try
            {
                var issueId = DateTimeOffset.Now.ToString("yyyy-MM-dd-HHmmss");

                var subject     = $"SANTEDB ISSUE MAILER #{issueId}";
                var body        = $"<html><body><p>{storageData.LoadProperty<SecurityUser>("CreatedBy")?.UserName ?? storageData?.Submitter?.LoadProperty<SecurityUser>("SecurityUser")?.UserName} has reported a bug</p><pre>{storageData.Note}</pre><p>You can reply directly to the reporter by pressing the Reply button in your mail client</p></body></html>";
                var attachments = storageData.Attachments.Select(a =>
                {
                    if (a is DiagnosticBinaryAttachment bin)
                    {
                        return(new NotificationAttachment(a.FileName ?? a.FileDescription, a.ContentType ?? "application/x-gzip", bin.Content));
                    }
                    else if (a is DiagnosticTextAttachment txt)
                    {
                        return(new NotificationAttachment(a.FileName ?? a.FileDescription, a.ContentType ?? "text/plain", txt.Content));
                    }
                    else
                    {
                        return(new NotificationAttachment(a.FileName ?? a.FileDescription, a.ContentType ?? "text/plain", $"Unknown attachment - {a}"));
                    }
                }).ToList();

                // Attach the application information
                using (var ms = new MemoryStream())
                {
                    XmlSerializer xsz = XmlModelSerializerFactory.Current.CreateSerializer(typeof(DiagnosticApplicationInfo));
                    xsz.Serialize(ms, storageData.ApplicationInfo);
                    attachments.Add(new NotificationAttachment("appinfo.xml", "text/xml", ms.ToArray()));
                }

                var notificationService = ApplicationServiceContext.Current.GetService <INotificationService>();
                var recipients          = this.m_configuration?.Recipients.Select(o => o.StartsWith("mailto:") ? o : $"mailto:{o}").ToArray();
                notificationService?.Send(recipients, subject, body, null, true, attachments.ToArray());

                // Invoke
                this.Inserted?.Invoke(this, new DataPersistedEventArgs <DiagnosticReport>(storageData, mode, overrideAuthContext));
                storageData.CorrelationId = issueId;
                storageData.Key           = Guid.NewGuid();
                return(storageData);
            }
            catch (Exception ex)
            {
                this.m_traceSource.TraceEvent(EventLevel.Error, "Error sending to E-Mail: {0}", ex);
                throw new InvalidOperationException("Error sending diagnostic reports to administrative contacts", ex);
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Remove the subscription
        /// </summary>
        public PubSubSubscriptionDefinition RemoveSubscription(Guid key)
        {
            this.m_policyEnforcementService.Demand(PermissionPolicyIdentifiers.DeletePubSubSubscription);

            var subscription = this.GetSubscription(key);

            if (subscription == null)
            {
                throw new KeyNotFoundException($"Subscription {key} not found");
            }

            var preEvt = new DataPersistingEventArgs <PubSubSubscriptionDefinition>(subscription, TransactionMode.Commit, AuthenticationContext.Current.Principal);

            this.UnSubscribing?.Invoke(this, preEvt);
            if (preEvt.Cancel)
            {
                this.m_tracer.TraceWarning("Pre-Event Hook for UnSubscribing issued cancel");
                return(preEvt.Data);
            }

            // Obsolete
            using (var conn = this.m_configuration.Provider.GetWriteConnection())
            {
                try
                {
                    conn.Open();
                    var dbExisting = conn.FirstOrDefault <DbSubscription>(o => o.Key == key);
                    if (dbExisting == null)
                    {
                        throw new KeyNotFoundException($"Subscription {key} not found");
                    }

                    // Get the authorship
                    var se = this.m_securityRepository.GetSecurityEntity(AuthenticationContext.Current.Principal);
                    if (se == null)
                    {
                        throw new KeyNotFoundException($"Unable to determine structure data for {AuthenticationContext.Current.Principal.Identity.Name}");
                    }
                    subscription.ObsoletedByKey = dbExisting.ObsoletedByKey = se.Key.Value;
                    subscription.ObsoletionTime = dbExisting.ObsoletionTime = DateTimeOffset.Now;
                    subscription.IsActive       = false;
                    conn.Update(dbExisting);
                    this.m_cache.Remove(key);

                    var retVal = this.MapInstance(conn, dbExisting);
                    this.UnSubscribed?.Invoke(this, new DataPersistedEventArgs <PubSubSubscriptionDefinition>(retVal, TransactionMode.Commit, AuthenticationContext.Current.Principal));
                    return(retVal);
                }
                catch (Exception e)
                {
                    throw new Exception($"Error obsoleting subscription {key}", e);
                }
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Save the specified entity (insert or update)
        /// </summary>
        public virtual TEntity Save(TEntity data)
        {
            // Demand permission
            this.DemandAlter(data);

            var persistenceService = ApplicationServiceContext.Current.GetService <IDataPersistenceService <TEntity> >();

            if (persistenceService == null)
            {
                throw new InvalidOperationException($"Unable to locate {nameof(IDataPersistenceService<TEntity>)}");
            }

            data = this.Validate(data);

            var businessRulesService = ApplicationServiceContext.Current.GetBusinessRulesService <TEntity>();

            try
            {
                var preSave = new DataPersistingEventArgs <TEntity>(data, AuthenticationContext.Current.Principal);
                this.Saving?.Invoke(this, preSave);
                if (preSave.Cancel)
                {
                    this.m_traceSource.TraceWarning("Persistence layer indicates pre-save cancel: {0}", data);
                    return(preSave.Data);
                }
                else
                {
                    data = preSave.Data; // Data may have been updated
                }
                if (data.Key.HasValue && persistenceService.Get(data.Key.Value, null, true, AuthenticationContext.Current.Principal) != null)
                {
                    data = businessRulesService?.BeforeUpdate(data) ?? data;
                    data = persistenceService.Update(data, TransactionMode.Commit, AuthenticationContext.Current.Principal);
                    businessRulesService?.AfterUpdate(data);
                }
                else
                {
                    data = businessRulesService?.BeforeInsert(data) ?? data;
                    data = persistenceService.Insert(data, TransactionMode.Commit, AuthenticationContext.Current.Principal);
                    businessRulesService?.AfterInsert(data);
                }

                this.Saved?.Invoke(this, new DataPersistedEventArgs <TEntity>(data, AuthenticationContext.Current.Principal));
                return(data);
            }
            catch (KeyNotFoundException)
            {
                return(this.Insert(data));
            }
        }
        /// <summary>
        /// Obsolete the specified data
        /// </summary>
        public virtual TEntity Obsolete(Guid key)
        {
            // Demand permission
            this.DemandDelete(key);

            var persistenceService = ApplicationServiceContext.Current.GetService <IDataPersistenceService <TEntity> >();

            if (persistenceService == null)
            {
                throw new InvalidOperationException(this.m_localizationService.FormatString("error.server.core.servicePersistence", new
                {
                    param = nameof(IDataPersistenceService <TEntity>)
                }));
            }

            var entity = persistenceService.Get(key, null, true, AuthenticationContext.Current.Principal);

            if (entity == null)
            {
                throw new KeyNotFoundException(this.m_localizationService.FormatString("error.type.KeyNotFoundException.notFound", new
                {
                    param = $"Entity {key}"
                }));
            }

            // Fire pre-persistence triggers
            var prePersistence = new DataPersistingEventArgs <TEntity>(entity, TransactionMode.Commit, AuthenticationContext.Current.Principal);

            this.Obsoleting?.Invoke(this, prePersistence);
            if (prePersistence.Cancel)
            {
                this.m_traceSource.TraceInfo("Pre-persistence event signal cancel obsolete: {0}", key);
                // Fired inserted trigger
                if (prePersistence.Success)
                {
                    this.Obsoleted?.Invoke(this, new DataPersistedEventArgs <TEntity>(prePersistence.Data, TransactionMode.Commit, AuthenticationContext.Current.Principal));
                }
                return(this.m_privacyService?.Apply(prePersistence.Data, AuthenticationContext.Current.Principal) ?? prePersistence.Data);
            }

            var businessRulesService = ApplicationServiceContext.Current.GetBusinessRulesService <TEntity>();

            entity = businessRulesService?.BeforeObsolete(entity) ?? entity;
            entity = persistenceService.Obsolete(entity, TransactionMode.Commit, AuthenticationContext.Current.Principal);
            entity = businessRulesService?.AfterObsolete(entity) ?? entity;

            this.Obsoleted?.Invoke(this, new DataPersistedEventArgs <TEntity>(entity, TransactionMode.Commit, AuthenticationContext.Current.Principal));

            return(this.m_privacyService?.Apply(entity, AuthenticationContext.Current.Principal) ?? entity);
        }
        /// <summary>
        /// Obsolete the specified data
        /// </summary>
        public virtual TEntity Obsolete(Guid key)
        {
            // Demand permission
            this.DemandDelete(key);

            var persistenceService = ApplicationContext.Current.GetService <IDataPersistenceService <TEntity> >();

            if (persistenceService == null)
            {
                throw new InvalidOperationException($"Unable to locate {nameof(IDataPersistenceService<TEntity>)}");
            }


            var entity = persistenceService.Get(key, null, false, AuthenticationContext.SystemPrincipal);

            if (entity == null)
            {
                throw new KeyNotFoundException($"Entity {key} not found");
            }

            var preEvent = new DataPersistingEventArgs <TEntity>(entity, TransactionMode.Commit, AuthenticationContext.Current.Principal);

            this.Obsoleting?.Invoke(this, preEvent);
            if (preEvent.Cancel)
            {
                this.m_traceSource.TraceWarning("Pre-persistence event indicates cancel");
                return(preEvent.Data);
            }
            entity = preEvent.Data;

            var businessRulesService = ApplicationContext.Current.GetService <IBusinessRulesService <TEntity> >();

            entity = businessRulesService?.BeforeObsolete(entity) ?? entity;
            entity = persistenceService.Obsolete(entity, TransactionMode.Commit, AuthenticationContext.Current.Principal);

            ApplicationContext.Current.GetService <IQueueManagerService>().Outbound.Enqueue(entity, SynchronizationOperationType.Obsolete);

            entity = businessRulesService?.AfterObsolete(entity) ?? entity;
            this.Obsoleted?.Invoke(this, new DataPersistedEventArgs <TEntity>(entity, TransactionMode.Commit, AuthenticationContext.Current.Principal));
            return(entity);
        }
Esempio n. 12
0
        /// <summary>
        /// Obsolete the specified data
        /// </summary>
        public virtual TEntity Obsolete(Guid key)
        {
            // Demand permission
            this.DemandDelete(key);

            var persistenceService = ApplicationServiceContext.Current.GetService <IDataPersistenceService <TEntity> >();

            if (persistenceService == null)
            {
                throw new InvalidOperationException($"Unable to locate {nameof(IDataPersistenceService<TEntity>)}");
            }

            var entity = persistenceService.Get(key, null, true, AuthenticationContext.Current.Principal);

            if (entity == null)
            {
                throw new KeyNotFoundException($"Entity {key} not found");
            }

            // Fire pre-persistence triggers
            var prePersistence = new DataPersistingEventArgs <TEntity>(entity, AuthenticationContext.Current.Principal);

            this.Obsoleting?.Invoke(this, prePersistence);
            if (prePersistence.Cancel)
            {
                this.m_traceSource.TraceWarning("Pre-persistence event signal cancel obsolete: {0}", key);
                return(prePersistence.Data);
            }

            var businessRulesService = ApplicationServiceContext.Current.GetBusinessRulesService <TEntity>();

            entity = businessRulesService?.BeforeObsolete(entity) ?? entity;
            entity = persistenceService.Obsolete(entity, TransactionMode.Commit, AuthenticationContext.Current.Principal);
            entity = businessRulesService?.AfterObsolete(entity) ?? entity;

            this.Obsoleted?.Invoke(this, new DataPersistedEventArgs <TEntity>(entity, AuthenticationContext.Current.Principal));

            return(entity);
        }
 /// <summary>
 /// Chain invoke a bundle on inserted
 /// </summary>
 protected void OnInserting(object sender, DataPersistingEventArgs <Bundle> e)
 {
     e.Data = this.ChainInvoke(sender, e, e.Data, nameof(OnInserting), typeof(DataPersistingEventArgs <>));
 }
 /// <summary>
 /// As a bundle, we call the base on the contents of the data
 /// </summary>
 protected void OnPrePersistenceValidate(object sender, DataPersistingEventArgs <Bundle> e)
 {
     e.Data = this.ChainInvoke(sender, e, e.Data, nameof(OnPrePersistenceValidate), typeof(DataPersistingEventArgs <>));
 }
        /// <summary>
        /// Obsolete the specified identified data
        /// </summary>
        /// <param name="data">Data.</param>
        public virtual TData Obsolete(TData data, TransactionMode mode, IPrincipal principal)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            else if (!data.Key.HasValue || data.Key == Guid.Empty)
            {
                throw new InvalidOperationException("Data missing key");
            }
#if PERFMON
            Stopwatch sw = new Stopwatch();
            sw.Start();
#endif
            DataPersistingEventArgs <TData> preArgs = new DataPersistingEventArgs <TData>(data, mode, principal);
            this.Obsoleting?.Invoke(this, preArgs);
            if (preArgs.Cancel)
            {
                this.m_tracer.TraceWarning("Pre-Event handler indicates abort for {0}", data);
                return(data);
            }

            // Obsolete object
            using (var context = this.CreateConnection(principal))
                try
                {
                    using (context.LockConnection())
                    {
                        try
                        {
                            this.m_tracer.TraceVerbose("OBSOLETE {0}", data);
                            context.Connection.BeginTransaction();

                            data = this.Obsolete(context, data);

                            if (mode == TransactionMode.Commit)
                            {
                                context.Connection.Commit();
                            }
                            else
                            {
                                context.Connection.Rollback();
                            }

                            // Remove from the cache
                            foreach (var itm in context.CacheOnCommit.AsParallel())
                            {
                                ApplicationContext.Current.GetService <IDataCachingService>().Remove(itm.Key.Value);
                            }
                        }
                        catch (Exception e)
                        {
                            this.m_tracer.TraceError("Error : {0}", e);
                            context.Connection.Rollback();
                            throw new LocalPersistenceException(SynchronizationOperationType.Obsolete, data, e);
                        }
                    }
                    this.Obsoleted?.Invoke(this, new DataPersistedEventArgs <TData>(data, mode, principal));

                    return(data);
                }
                catch (SQLiteException e)
                {
                    this.m_tracer.TraceError("Error obsoleting data {1} : {0}", e, context.Connection);
                    throw new DataPersistenceException($"Database error obsoleting {data}", e);
                }
            catch (Exception e) { throw new DataPersistenceException($"Error obsoleting {data}", e); }
#if PERFMON
            finally
            {
                sw.Stop();
                ApplicationContext.Current.PerformanceLog(typeof(TData).Name, nameof(Obsolete), "Complete", sw.Elapsed);
            }
#endif
        }
        /// <summary>
        /// Insert the specified data.
        /// </summary>
        /// <param name="data">Data.</param>
        public virtual TData Insert(TData data, TransactionMode mode, IPrincipal principal)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            DataPersistingEventArgs <TData> preArgs = new DataPersistingEventArgs <TData>(data, mode, principal);

            this.Inserting?.Invoke(this, preArgs);
            if (preArgs.Cancel)
            {
                this.m_tracer.TraceWarning("Pre-Event handler indicates abort insert for {0}", data);
                return(data);
            }

#if PERFMON
            Stopwatch sw = new Stopwatch();
            sw.Start();
#endif

            // Persist objectel
            using (var context = this.CreateConnection(principal))
                try
                {
                    using (context.LockConnection())
                    {
                        try
                        {
                            // Does this object already exist?
                            if (data.Key.HasValue && this.Get(context, data.Key.Value) != null)
                            {
                                throw new DuplicateKeyException($"Object {typeof(TData).Name} with key {data.Key} already exists");
                            }

                            this.m_tracer.TraceVerbose("INSERT {0}", data);

                            context.Connection.BeginTransaction();
                            data = this.Insert(context, data);

                            if (mode == TransactionMode.Commit)
                            {
                                context.Connection.Commit();
                            }
                            else
                            {
                                context.Connection.Rollback();
                            }
                            // Remove from the cache
                            foreach (var itm in context.CacheOnCommit.AsParallel())
                            {
                                ApplicationContext.Current.GetService <IDataCachingService>().Add(itm);
                            }
                        }
                        catch (Exception e)
                        {
                            this.m_tracer.TraceError("Error : {0}", e);
                            context.Connection.Rollback();
                            throw new LocalPersistenceException(SynchronizationOperationType.Insert, data, e);
                        }
                    }
                    this.Inserted?.Invoke(this, new DataPersistedEventArgs <TData>(data, mode, principal));
                    return(data);
                }
                catch (SQLiteException e)
                {
                    this.m_tracer.TraceError("Error inserting data {1} : {0}", e, context.Connection);
                    throw new DataPersistenceException($"Database error inserting {data}", e);
                }
            catch (Exception e)
            {
                throw new DataPersistenceException($"Error inserting {data}", e);
            }

#if PERFMON
            finally
            {
                sw.Stop();
                ApplicationContext.Current.PerformanceLog(typeof(TData).Name, nameof(Insert), "Complete", sw.Elapsed);
            }
#endif
        }
 /// <summary>
 /// Fire inserting event
 /// </summary>
 protected void FireInserting(DataPersistingEventArgs <TData> evt)
 {
     this.Inserting?.Invoke(this, evt);
 }
Esempio n. 18
0
        /// <summary>
        /// Register a subscription for <paramref name="modelType"/>
        /// </summary>
        public PubSubSubscriptionDefinition RegisterSubscription(Type modelType, string name, string description, PubSubEventType events, string hdsiFilter, Guid channelId, String supportAddress = null, DateTimeOffset?notBefore = null, DateTimeOffset?notAfter = null)
        {
            this.m_policyEnforcementService.Demand(PermissionPolicyIdentifiers.CreatePubSubSubscription);

            var subscription = new PubSubSubscriptionDefinition()
            {
                ChannelKey       = channelId,
                Event            = events,
                Filter           = String.IsNullOrEmpty(hdsiFilter) ? null : new List <string>(hdsiFilter.Split('&')),
                IsActive         = false,
                Name             = name,
                Description      = description,
                SupportContact   = supportAddress,
                NotBefore        = notBefore?.DateTime,
                NotAfter         = notAfter?.DateTime,
                ResourceTypeName = modelType.GetSerializationName()
            };

            var preEvent = new DataPersistingEventArgs <PubSubSubscriptionDefinition>(subscription, TransactionMode.Commit, AuthenticationContext.Current.Principal);

            this.Subscribing?.Invoke(this, preEvent);
            if (preEvent.Cancel)
            {
                this.m_tracer.TraceWarning("Pre-Event Hook Indicates Cancel");
                return(preEvent.Data);
            }

            using (var conn = this.m_configuration.Provider.GetWriteConnection())
            {
                try
                {
                    conn.Open();
                    using (var tx = conn.BeginTransaction())
                    {
                        // First construct db instance
                        var dbSubscription = this.m_mapper.MapModelInstance <PubSubSubscriptionDefinition, DbSubscription>(subscription);

                        // Get the authorship
                        var se = this.m_securityRepository.GetSecurityEntity(AuthenticationContext.Current.Principal);
                        if (se == null)
                        {
                            throw new KeyNotFoundException($"Unable to determine structure data for {AuthenticationContext.Current.Principal.Identity.Name}");
                        }
                        dbSubscription.CreatedByKey = se.Key.Value;
                        dbSubscription.CreationTime = DateTimeOffset.Now;
                        dbSubscription = conn.Insert(dbSubscription);

                        // Insert settings
                        if (subscription.Filter != null)
                        {
                            foreach (var itm in subscription.Filter)
                            {
                                conn.Insert(new DbSubscriptionFilter()
                                {
                                    SubscriptionKey = dbSubscription.Key.Value,
                                    Filter          = itm
                                });
                            }
                        }

                        tx.Commit();

                        subscription = this.MapInstance(conn, dbSubscription);
                        this.Subscribed?.Invoke(this, new DataPersistedEventArgs <PubSubSubscriptionDefinition>(subscription, TransactionMode.Commit, AuthenticationContext.Current.Principal));
                        this.m_cache?.Add(subscription);
                        return(subscription);
                    }
                }
                catch (Exception e)
                {
                    throw new Exception($"Error inserting subscription {subscription}", e);
                }
            }
        }
        /// <summary>
        /// Save the specified entity (insert or update)
        /// </summary>
        public virtual TEntity Save(TEntity data)
        {
            // Demand permission
            this.DemandAlter(data);

            var persistenceService = ApplicationContext.Current.GetService <IDataPersistenceService <TEntity> >();

            if (persistenceService == null)
            {
                throw new InvalidOperationException($"Unable to locate {nameof(IDataPersistenceService<TEntity>)}");
            }

            data = this.Validate(data);

            var businessRulesService = ApplicationContext.Current.GetService <IBusinessRulesService <TEntity> >();

            try
            {
                var preEvent = new DataPersistingEventArgs <TEntity>(data, TransactionMode.Commit, AuthenticationContext.Current.Principal);
                this.Saving?.Invoke(this, preEvent);
                if (preEvent.Cancel)
                {
                    this.m_traceSource.TraceWarning("Pre-persistence event indicates cancel");
                    return(preEvent.Data);
                }
                data = preEvent.Data;

                // We need to know what the old version looked like so we can patch it
                TEntity old = null;

                // Data key
                if (data.Key.HasValue)
                {
                    old = persistenceService.Get(data.Key.Value, null, false, AuthenticationContext.SystemPrincipal) as TEntity;
                    if (old is Entity)
                    {
                        old = (TEntity)(old as Entity)?.Copy();
                    }
                    else if (old is Act)
                    {
                        old = (TEntity)(old as Act)?.Copy();
                    }
                }

                // HACK: Lookup by ER src<>trg
                if (old == null && typeof(TEntity) == typeof(EntityRelationship))
                {
                    var tr  = 0;
                    var erd = data as EntityRelationship;
                    old = (TEntity)(persistenceService as IDataPersistenceService <EntityRelationship>).Query(o => o.SourceEntityKey == erd.SourceEntityKey && o.TargetEntityKey == erd.TargetEntityKey, 0, 1, out tr, AuthenticationContext.SystemPrincipal).OfType <EntityRelationship>().FirstOrDefault().Clone();
                }

                // Old does not exist
                if (old == null)
                {
                    data = businessRulesService?.BeforeInsert(data) ?? data;
                    data = persistenceService.Insert(data, TransactionMode.Commit, AuthenticationContext.Current.Principal);
                    ApplicationContext.Current.GetService <IQueueManagerService>()?.Outbound.Enqueue(data, SynchronizationOperationType.Insert);
                    data = businessRulesService?.AfterInsert(data) ?? data;
                    this.Saved?.Invoke(this, new DataPersistedEventArgs <TEntity>(data, TransactionMode.Commit, AuthenticationContext.Current.Principal));
                }
                else
                {
                    data = businessRulesService?.BeforeUpdate(data) ?? data;
                    data = persistenceService.Update(data, TransactionMode.Commit, AuthenticationContext.Current.Principal);

                    // Use patches
                    if (ApplicationContext.Current.Configuration.GetSection <SynchronizationConfigurationSection>().UsePatches)
                    {
                        var diff = ApplicationContext.Current.GetService <IPatchService>()?.Diff(old, this.Get(data.Key.Value), "participation");
                        if (diff != null)
                        {
                            ApplicationContext.Current.GetService <IQueueManagerService>()?.Outbound.Enqueue(diff, SynchronizationOperationType.Update);
                        }
                        else
                        {
                            ApplicationContext.Current.GetService <IQueueManagerService>()?.Outbound.Enqueue(data, SynchronizationOperationType.Update);
                        }
                    }
                    else
                    {
                        ApplicationContext.Current.GetService <IQueueManagerService>()?.Outbound.Enqueue(data, SynchronizationOperationType.Update);
                    }


                    data = businessRulesService?.AfterUpdate(data) ?? data;
                    this.Saved?.Invoke(this, new DataPersistedEventArgs <TEntity>(data, TransactionMode.Commit, AuthenticationContext.Current.Principal));
                }

                return(data);
            }
            catch (KeyNotFoundException)
            {
                data = businessRulesService?.BeforeInsert(data) ?? data;
                data = persistenceService.Insert(data, TransactionMode.Commit, AuthenticationContext.Current.Principal);
                ApplicationContext.Current.GetService <IQueueManagerService>()?.Outbound.Enqueue(data, SynchronizationOperationType.Insert);
                data = businessRulesService?.AfterInsert(data) ?? data;
                this.Saved?.Invoke(this, new DataPersistedEventArgs <TEntity>(data, TransactionMode.Commit, AuthenticationContext.Current.Principal));
                return(data);
            }
        }
Esempio n. 20
0
        /// <summary>
        /// Obsoletes the specified object
        /// </summary>
        public TData Obsolete(TData data, TransactionMode mode, IPrincipal overrideAuthContext)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            else if (data.Key == Guid.Empty)
            {
                throw new InvalidOperationException("Data missing key");
            }

            DataPersistingEventArgs <TData> preArgs = new DataPersistingEventArgs <TData>(data, mode, overrideAuthContext);

            this.Obsoleting?.Invoke(this, preArgs);
            if (preArgs.Cancel)
            {
                this.m_tracer.TraceEvent(EventLevel.Warning, "Pre-Event handler indicates abort for {0}", data);
                return(data);
            }

            // Obsolete object
            using (var connection = this.m_settingsProvider.GetConfiguration().Provider.GetWriteConnection())
            {
                try
                {
                    connection.Open();
                    using (IDbTransaction tx = connection.BeginTransaction())
                        try
                        {
                            //connection.Connection.Open();

                            this.m_tracer.TraceEvent(EventLevel.Verbose, "OBSOLETE {0}", data);
                            connection.EstablishProvenance(overrideAuthContext, (data as BaseEntityData)?.ObsoletedByKey);
                            data = this.Obsolete(connection, data);

                            if (mode == TransactionMode.Commit)
                            {
                                tx.Commit();
                                var cacheService = ApplicationServiceContext.Current.GetService <IDataCachingService>();
                                cacheService?.Remove(data);
                            }
                            else
                            {
                                tx.Rollback();
                            }

                            var args = new DataPersistedEventArgs <TData>(data, mode, overrideAuthContext);

                            this.Obsoleted?.Invoke(this, args);

                            return(data);
                        }
                        catch (Exception e)
                        {
                            this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0}", e);
                            tx?.Rollback();
                            throw new DataPersistenceException(e.Message, e);
                        }
                    finally
                    {
                    }
                }
                finally
                {
                }
            }
        }
Esempio n. 21
0
        /// <summary>
        /// Update the specified container
        /// </summary>
        /// <param name="data">The data to be updated</param>
        /// <param name="principal">The principal for authorization</param>
        /// <param name="mode">The mode of operation</param>
        /// <returns>The updated model</returns>
        public TModel Update(TModel data, TransactionMode mode, IPrincipal principal)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            else if (data.Key == Guid.Empty)
            {
                throw new InvalidOperationException("Data missing key");
            }

            DataPersistingEventArgs <TModel> preArgs = new DataPersistingEventArgs <TModel>(data, mode, principal);

            this.Updating?.Invoke(this, preArgs);
            if (preArgs.Cancel)
            {
                this.m_tracer.TraceWarning("Pre-Event handler indicates abort update for {0}", data);
                return(data);
            }

            // Persist object
            using (var connection = AdoAuditPersistenceService.GetConfiguration().Provider.GetWriteConnection())
            {
                connection.Open();
                using (IDbTransaction tx = connection.BeginTransaction())
                    try
                    {
                        //connection.Connection.Open();
                        connection.EstablishProvenance(principal, (data as NonVersionedEntityData)?.UpdatedByKey ?? (data as BaseEntityData)?.CreatedByKey);

                        this.m_tracer.TraceVerbose("UPDATE {0}", data);

                        data = this.UpdateInternal(connection, data, principal);
                        connection.AddCacheCommit(data);
                        data.LoadState = LoadState.FullLoad; // We just persisted this so it is fully loaded

                        if (mode == TransactionMode.Commit)
                        {
                            tx.Commit();
                            foreach (var itm in connection.CacheOnCommit)
                            {
                                ApplicationServiceContext.Current.GetService <IDataCachingService>()?.Add(itm);
                            }
                        }
                        else
                        {
                            tx.Rollback();
                        }

                        var args = new DataPersistedEventArgs <TModel>(data, mode, principal);

                        this.Updated?.Invoke(this, args);

                        return(data);
                    }
                    catch (DbException e)
                    {
#if DEBUG
                        this.m_tracer.TraceError("Error : {0} -- {1}", e, this.ObjectToString(data));
#else
                        this.m_tracer.TraceError("Error : {0}", e.Message);
#endif
                        tx?.Rollback();

                        this.TranslateDbException(e);
                        throw;
                    }
                catch (Exception e)
                {
#if DEBUG
                    this.m_tracer.TraceError("Error : {0} -- {1}", e, this.ObjectToString(data));
#else
                    this.m_tracer.TraceError("Error : {0}", e.Message);
#endif
                    tx?.Rollback();

                    // if the exception is key not found, we want the caller to know
                    // so that a potential insert can take place
                    if (e is KeyNotFoundException)
                    {
                        throw new KeyNotFoundException(e.Message, e);
                    }

                    // if the exception is anything else, we want to throw a data persistence exception
                    throw new DataPersistenceException(e.Message, e);
                }
                finally
                {
                }
            }
        }
        /// <summary>
        /// Save the specified entity (insert or update)
        /// </summary>
        public virtual TEntity Save(TEntity data)
        {
            // Demand permission
            this.DemandAlter(data);

            var persistenceService = ApplicationServiceContext.Current.GetService <IDataPersistenceService <TEntity> >();

            if (persistenceService == null)
            {
                throw new InvalidOperationException(this.m_localizationService.FormatString("error.server.core.servicePersistence", new
                {
                    param = nameof(IDataPersistenceService <TEntity>)
                }));
            }

            data = this.Validate(data);

            var businessRulesService = ApplicationServiceContext.Current.GetBusinessRulesService <TEntity>();

            try
            {
                if (this.m_privacyService?.ValidateWrite(data, AuthenticationContext.Current.Principal) == false)
                {
                    this.ThrowPrivacyValidationException(data);
                }

                var preSave = new DataPersistingEventArgs <TEntity>(data, TransactionMode.Commit, AuthenticationContext.Current.Principal);
                this.Saving?.Invoke(this, preSave);
                if (preSave.Cancel)
                {
                    this.m_traceSource.TraceInfo("Persistence layer indicates pre-save cancel: {0}", data);
                    // Fired inserted trigger
                    if (preSave.Success)
                    {
                        this.Saved?.Invoke(this, new DataPersistedEventArgs <TEntity>(preSave.Data, TransactionMode.Commit, AuthenticationContext.Current.Principal));
                    }
                    return(this.m_privacyService?.Apply(preSave.Data, AuthenticationContext.Current.Principal) ?? preSave.Data);
                }
                else
                {
                    data = preSave.Data; // Data may have been updated
                }
                if (data.Key.HasValue && persistenceService.Get(data.Key.Value, null, true, AuthenticationContext.Current.Principal) != null)
                {
                    data = businessRulesService?.BeforeUpdate(data) ?? data;
                    data = persistenceService.Update(data, TransactionMode.Commit, AuthenticationContext.Current.Principal);
                    businessRulesService?.AfterUpdate(data);
                }
                else
                {
                    data = businessRulesService?.BeforeInsert(data) ?? data;
                    data = persistenceService.Insert(data, TransactionMode.Commit, AuthenticationContext.Current.Principal);
                    businessRulesService?.AfterInsert(data);
                }

                this.Saved?.Invoke(this, new DataPersistedEventArgs <TEntity>(data, TransactionMode.Commit, AuthenticationContext.Current.Principal));
                return(this.m_privacyService?.Apply(data, AuthenticationContext.Current.Principal) ?? data);
            }
            catch (KeyNotFoundException)
            {
                return(this.Insert(data));
            }
        }
Esempio n. 23
0
        /// <summary>
        /// Activates or de-activates <paramref name="key"/>
        /// </summary>
        public PubSubSubscriptionDefinition ActivateSubscription(Guid key, bool isActive)
        {
            this.m_policyEnforcementService.Demand(PermissionPolicyIdentifiers.EnablePubSubSubscription);

            // perform activation
            using (var conn = this.m_configuration.Provider.GetWriteConnection())
            {
                try
                {
                    conn.Open();
                    var dbExisting = conn.FirstOrDefault <DbSubscription>(o => o.Key == key);
                    if (dbExisting == null)
                    {
                        throw new KeyNotFoundException($"Subscription {key} not found");
                    }

                    var subscription = this.MapInstance(conn, dbExisting);
                    var preEvt       = new DataPersistingEventArgs <PubSubSubscriptionDefinition>(subscription, TransactionMode.Commit, AuthenticationContext.Current.Principal);
                    if (isActive)
                    {
                        this.Activating?.Invoke(this, preEvt);
                    }
                    else
                    {
                        this.DeActivating?.Invoke(this, preEvt);
                    }

                    if (preEvt.Cancel)
                    {
                        this.m_tracer.TraceWarning("Pre-Event Hook for Activation issued cancel");
                        return(preEvt.Data);
                    }

                    var se = this.m_securityRepository.GetSecurityEntity(AuthenticationContext.Current.Principal);
                    if (se == null)
                    {
                        throw new SecurityException($"Cannot determine SID for {AuthenticationContext.Current.Principal.Identity.Name}");
                    }
                    dbExisting.IsActive             = isActive;
                    subscription.IsActive           = isActive;
                    subscription.UpdatedByKey       = dbExisting.UpdatedByKey = se.Key.Value;
                    subscription.UpdatedTime        = dbExisting.UpdatedTime = DateTimeOffset.Now;
                    dbExisting.ObsoletionTime       = null;
                    dbExisting.ObsoletedByKey       = null;
                    dbExisting.ObsoletedBySpecified = dbExisting.ObsoletionTimeSpecified = true;
                    conn.Update(dbExisting);
                    this.m_cache.Remove(key);

                    if (isActive)
                    {
                        this.Activated?.Invoke(this, new DataPersistedEventArgs <PubSubSubscriptionDefinition>(subscription, TransactionMode.Commit, AuthenticationContext.Current.Principal));
                    }
                    else
                    {
                        this.DeActivated?.Invoke(this, new DataPersistedEventArgs <PubSubSubscriptionDefinition>(subscription, TransactionMode.Commit, AuthenticationContext.Current.Principal));
                    }

                    return(subscription);
                }
                catch (Exception e)
                {
                    throw new Exception($"Error obsoleting subscription {key}", e);
                }
            }
        }
        /// <summary>
        /// Insert the specified audit into the database
        /// </summary>
        public AuditData Insert(AuditData storageData, TransactionMode mode, IPrincipal overrideAuthContext = null)
        {
            // Pre-event trigger
            var preEvtData = new DataPersistingEventArgs <AuditData>(storageData, mode, overrideAuthContext);

            this.Inserting?.Invoke(this, preEvtData);
            if (preEvtData.Cancel)
            {
                this.m_traceSource.TraceEvent(EventLevel.Warning, "Pre-Event handler indicates abort insert {0}", storageData);
                return(storageData);
            }

            // Insert
            using (var context = this.m_configuration.Provider.GetWriteConnection())
            {
                IDbTransaction tx = null;
                try
                {
                    context.Open();
                    tx = context.BeginTransaction();

                    // Insert core
                    var dbAudit = this.m_mapper.MapModelInstance <AuditData, DbAuditData>(storageData);

                    var eventId = storageData.EventTypeCode;
                    if (eventId != null)
                    {
                        dbAudit.EventTypeCode = this.GetOrCreateAuditCode(context, eventId).Key;
                    }

                    dbAudit.CreationTime = DateTimeOffset.Now;
                    storageData.Key      = Guid.NewGuid();
                    dbAudit.Key          = storageData.Key.Value;
                    context.Insert(dbAudit);

                    // Insert secondary properties
                    if (storageData.Actors != null)
                    {
                        foreach (var act in storageData.Actors)
                        {
                            var roleCode = this.GetOrCreateAuditCode(context, act.ActorRoleCode.FirstOrDefault());

                            DbAuditActor dbAct = null;
                            if (roleCode != null)
                            {
                                dbAct = context.FirstOrDefault <DbAuditActor>(o => o.UserName == act.UserName && o.ActorRoleCode == roleCode.Key);
                            }
                            else
                            {
                                dbAct = context.FirstOrDefault <DbAuditActor>(o => o.UserName == act.UserName && o.ActorRoleCode == Guid.Empty);
                            }

                            if (dbAct == null)
                            {
                                dbAct = this.m_mapper.MapModelInstance <AuditActorData, DbAuditActor>(act);
                                dbAct.ActorRoleCode = roleCode?.Key ?? Guid.Empty;
                                dbAct = context.Insert(dbAct);
                            }
                            context.Insert(new DbAuditActorAssociation()
                            {
                                TargetKey       = dbAct.Key,
                                SourceKey       = dbAudit.Key,
                                UserIsRequestor = act.UserIsRequestor,
                                AccessPoint     = act.NetworkAccessPointId
                            });
                        }
                    }

                    // Audit objects
                    if (storageData.AuditableObjects != null)
                    {
                        foreach (var ao in storageData.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.Key;

                            if (ao.CustomIdTypeCode != null)
                            {
                                var code = this.GetOrCreateAuditCode(context, ao.CustomIdTypeCode);
                                dbAo.CustomIdType = code.Key;
                            }

                            dbAo = context.Insert(dbAo);

                            if (ao.ObjectData?.Count > 0)
                            {
                                foreach (var od in ao.ObjectData)
                                {
                                    context.Insert(new DbAuditObjectData()
                                    {
                                        Name     = od.Key,
                                        Value    = od.Value,
                                        ObjectId = dbAo.Key
                                    });
                                }
                            }
                        }
                    }

                    // metadata
                    if (storageData.Metadata != null)
                    {
                        foreach (var meta in storageData.Metadata.Where(o => !String.IsNullOrEmpty(o.Value) && o.Key != AuditMetadataKey.CorrelationToken))
                        {
                            var kv = context.FirstOrDefault <DbAuditMetadataValue>(o => o.Value == meta.Value);
                            if (kv == null)
                            {
                                kv = context.Insert(new DbAuditMetadataValue()
                                {
                                    // TODO: Make this a common extension function (to trim)
                                    Value = meta.Value.Substring(0, meta.Value.Length > 256 ? 256 : meta.Value.Length)
                                });
                            }

                            context.Insert(new DbAuditMetadata()
                            {
                                AuditId     = dbAudit.Key,
                                MetadataKey = (int)meta.Key,
                                ValueId     = kv.Key
                            });
                        }
                    }

                    if (mode == TransactionMode.Commit)
                    {
                        tx.Commit();
                    }
                    else
                    {
                        tx.Rollback();
                    }

                    var args = new DataPersistedEventArgs <AuditData>(storageData, mode, overrideAuthContext);

                    this.Inserted?.Invoke(this, args);

                    return(storageData);
                }
                catch (Exception ex)
                {
                    tx?.Rollback();
                    throw new Exception($"Error inserting audit {storageData.Key}", ex);
                }
            }
        }
Esempio n. 25
0
        /// <summary>
        /// Insert the specified audit into the database
        /// </summary>
        public AuditData Insert(AuditData storageData, TransactionMode mode, IPrincipal overrideAuthContext = null)
        {
            // Pre-event trigger
            var preEvtData = new DataPersistingEventArgs <AuditData>(storageData, overrideAuthContext);

            this.Inserting?.Invoke(this, preEvtData);
            if (preEvtData.Cancel)
            {
                this.m_traceSource.TraceEvent(EventLevel.Warning, "Pre-Event handler indicates abort insert {0}", storageData);
                return(storageData);
            }

            // Insert
            using (var context = this.m_configuration.Provider.GetWriteConnection())
            {
                IDbTransaction tx = null;
                try
                {
                    context.Open();
                    tx = context.BeginTransaction();

                    // Insert core
                    var dbAudit = this.m_mapper.MapModelInstance <AuditData, DbAuditData>(storageData);

                    var eventId = storageData.EventTypeCode;
                    if (eventId != null)
                    {
                        var existing = context.FirstOrDefault <DbAuditCode>(o => o.Code == eventId.Code && o.CodeSystem == eventId.CodeSystem);
                        if (existing == null)
                        {
                            Guid codeId = Guid.NewGuid();
                            dbAudit.EventTypeCode = codeId;
                            context.Insert(new DbAuditCode()
                            {
                                Code = eventId.Code, CodeSystem = eventId.CodeSystem, Key = codeId
                            });
                        }
                        else
                        {
                            dbAudit.EventTypeCode = existing.Key;
                        }
                    }

                    dbAudit.CreationTime = DateTime.Now;
                    storageData.Key      = Guid.NewGuid();
                    dbAudit.Key          = storageData.Key.Value;
                    context.Insert(dbAudit);

                    // Insert secondary properties
                    if (storageData.Actors != null)
                    {
                        foreach (var act in storageData.Actors)
                        {
                            var dbAct = context.FirstOrDefault <DbAuditActor>(o => o.UserName == act.UserName);
                            if (dbAct == null)
                            {
                                dbAct     = this.m_mapper.MapModelInstance <AuditActorData, DbAuditActor>(act);
                                dbAct.Key = Guid.NewGuid();
                                var roleCode = act.ActorRoleCode?.FirstOrDefault();
                                if (roleCode != null)
                                {
                                    var existing = context.FirstOrDefault <DbAuditCode>(o => o.Code == roleCode.Code && o.CodeSystem == roleCode.CodeSystem);
                                    if (existing == null)
                                    {
                                        dbAct.ActorRoleCode = Guid.NewGuid();
                                        context.Insert(new DbAuditCode()
                                        {
                                            Code = roleCode.Code, CodeSystem = roleCode.CodeSystem, Key = dbAct.ActorRoleCode
                                        });
                                    }
                                    else
                                    {
                                        dbAct.ActorRoleCode = existing.Key;
                                    }
                                }
                                context.Insert(dbAct);
                            }
                            context.Insert(new DbAuditActorAssociation()
                            {
                                TargetKey       = dbAct.Key,
                                SourceKey       = dbAudit.Key,
                                UserIsRequestor = act.UserIsRequestor,
                                AccessPoint     = act.NetworkAccessPointId,
                                Key             = Guid.NewGuid()
                            });
                        }
                    }

                    // Audit objects
                    if (storageData.AuditableObjects != null)
                    {
                        foreach (var ao in storageData.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.Key;
                            dbAo.Key           = Guid.NewGuid();
                            context.Insert(dbAo);
                        }
                    }

                    // metadata
                    if (storageData.Metadata != null)
                    {
                        foreach (var meta in storageData.Metadata.Where(o => !String.IsNullOrEmpty(o.Value)))
                        {
                            context.Insert(new DbAuditMetadata()
                            {
                                AuditId     = dbAudit.Key,
                                MetadataKey = (int)meta.Key,
                                Value       = meta.Value
                            });
                        }
                    }

                    if (mode == TransactionMode.Commit)
                    {
                        tx.Commit();
                    }
                    else
                    {
                        tx.Rollback();
                    }

                    var args = new DataPersistedEventArgs <AuditData>(storageData, overrideAuthContext);

                    this.Inserted?.Invoke(this, args);

                    return(storageData);
                }
                catch (Exception ex)
                {
                    tx?.Rollback();
                    throw new Exception($"Error inserting audit {storageData.Key}", ex);
                }
            }
        }
Esempio n. 26
0
        /// <summary>
        /// Represents when the ADT registration occurs
        /// </summary>
        protected void AdtPatientRegistrationInterceptor_Behavior(object sender, DataPersistingEventArgs <Patient> e)
        {
            AuthenticationContext.Current = new AuthenticationContext(AuthenticationContext.SystemPrincipal);

            e.Cancel = true;

            Patient pat = e.Data;

            // Perform notification
            IMessage notificationMessage;
            IGroup   patientGroup;

            if (pat.PreviousVersionKey == null)
            {
                // Set the tag value and send an ADMIT
                patientGroup = notificationMessage = new ADT_A01();
                (notificationMessage.GetStructure("MSH") as MSH).MessageType.TriggerEvent.Value     = "A04";
                (notificationMessage.GetStructure("MSH") as MSH).MessageType.MessageStructure.Value = "ADT_A01";
            }
            else if (pat.Relationships.Any(o => o.RelationshipTypeKey == EntityRelationshipTypeKeys.Replaces && o.EffectiveVersionSequenceId == pat.VersionSequence))
            {
                // Set the tag value and send an ADMIT
                notificationMessage = new ADT_A39();
                patientGroup        = (notificationMessage as ADT_A39).GetPATIENT();
                (notificationMessage.GetStructure("MSH") as MSH).MessageType.TriggerEvent.Value     = "A40";
                (notificationMessage.GetStructure("MSH") as MSH).MessageType.MessageStructure.Value = "ADT_A40";

                foreach (var mrg in pat.Relationships.Where(o => o.RelationshipTypeKey == EntityRelationshipTypeKeys.Replaces && o.EffectiveVersionSequenceId == pat.VersionSequence))
                {
                    var seg = patientGroup.GetStructure("MRG", patientGroup.GetAll("MRG").Length) as MRG;

                    if (this.Configuration.ExportDomains.Any(o => o.DomainName == this.m_configuration.LocalAuthority.DomainName))
                    {
                        var key = seg.PriorAlternatePatientIDRepetitionsUsed;
                        seg.GetPriorAlternatePatientID(key).IDNumber.Value                           = mrg.TargetEntityKey.Value.ToString();
                        seg.GetPriorAlternatePatientID(key).IdentifierTypeCode.Value                 = "PI";
                        seg.GetPriorAlternatePatientID(key).AssigningAuthority.NamespaceID.Value     = this.m_configuration.LocalAuthority.DomainName;
                        seg.GetPriorAlternatePatientID(key).AssigningAuthority.UniversalID.Value     = this.m_configuration.LocalAuthority.Oid;
                        seg.GetPriorAlternatePatientID(key).AssigningAuthority.UniversalIDType.Value = "ISO";
                    }

                    // Alternate identifiers
                    foreach (var extrn in pat.Identifiers)
                    {
                        var key = seg.PriorAlternatePatientIDRepetitionsUsed;
                        if (this.Configuration.ExportDomains.Any(o => o.DomainName == extrn.LoadProperty <AssigningAuthority>("Authority").DomainName))
                        {
                            seg.GetPriorAlternatePatientID(key).IDNumber.Value                           = extrn.Value;
                            seg.GetPriorAlternatePatientID(key).IdentifierTypeCode.Value                 = "PT";
                            seg.GetPriorAlternatePatientID(key).AssigningAuthority.NamespaceID.Value     = extrn.LoadProperty <AssigningAuthority>("Authority")?.DomainName;
                            seg.GetPriorAlternatePatientID(key).AssigningAuthority.UniversalID.Value     = extrn.LoadProperty <AssigningAuthority>("Authority")?.Oid;
                            seg.GetPriorAlternatePatientID(key).AssigningAuthority.UniversalIDType.Value = "ISO";
                        }
                    }
                }
            }
            else
            {
                // Set the tag value and send an ADMIT
                patientGroup = notificationMessage = new ADT_A01();
                (notificationMessage.GetStructure("MSH") as MSH).MessageType.TriggerEvent.Value     = "A08";
                (notificationMessage.GetStructure("MSH") as MSH).MessageType.MessageStructure.Value = "ADT_A08";
            }

            if (!String.IsNullOrEmpty(this.Configuration.Version))
            {
                (notificationMessage.GetStructure("MSH") as MSH).VersionID.VersionID.Value = this.Configuration.Version;
            }

            // Add SFT
            if (new Version(this.Configuration.Version ?? "2.5") >= new Version(2, 4))
            {
                (notificationMessage.GetStructure("SFT", 0) as SFT).SetDefault();
            }

            // Create the PID segment
            SegmentHandlers.GetSegmentHandler("PID").Create(e.Data, patientGroup, this.Configuration.ExportDomains.ToArray());
            SegmentHandlers.GetSegmentHandler("PD1").Create(e.Data, patientGroup, this.Configuration.ExportDomains.ToArray());
            SegmentHandlers.GetSegmentHandler("NK1").Create(e.Data, patientGroup, this.Configuration.ExportDomains.ToArray());
            //SegmentHandlers.GetSegmentHandler("EVN").Create(e.Data, patientGroup, this.Configuration.ExportDomains.ToArray());

            foreach (var itm in this.Configuration.Endpoints)
            {
                try
                {
                    // TODO: Create an HL7 Queue
                    (notificationMessage.GetStructure("MSH") as MSH).SetDefault(itm.ReceivingDevice, itm.ReceivingFacility, itm.SecurityToken);
                    var response = itm.GetSender().SendAndReceive(notificationMessage);

                    if (!(response.GetStructure("MSA") as MSA).AcknowledgmentCode.Value.EndsWith("A"))
                    {
                        throw new HL7Exception("Remote server rejected message");
                    }
                }
                catch (Exception ex)
                {
                    this.m_tracer.TraceEvent(EventLevel.Error, "Error dispatching message {0} to {1}: {2} \r\n {3}", pat, itm.Address, ex, new PipeParser().Encode(notificationMessage));
                }
            }
        }
Esempio n. 27
0
        /// <summary>
        /// Inserts the specified data
        /// </summary>
        public TData Insert(TData data, TransactionMode mode, IPrincipal overrideAuthContext)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            DataPersistingEventArgs <TData> preArgs = new DataPersistingEventArgs <TData>(data, mode, overrideAuthContext);

            this.Inserting?.Invoke(this, preArgs);
            if (preArgs.Cancel)
            {
                this.m_tracer.TraceEvent(EventLevel.Warning, "Pre-Event handler indicates abort insert for {0}", data);
                return(data);
            }

            // Persist object
            using (var connection = this.m_settingsProvider.GetConfiguration().Provider.GetWriteConnection())
            {
                try
                {
                    connection.Open();
                    using (IDbTransaction tx = connection.BeginTransaction())
                        try
                        {
                            // Disable inserting duplicate classified objects
                            connection.EstablishProvenance(overrideAuthContext, (data as BaseEntityData)?.CreatedByKey);
                            var existing = data.TryGetExisting(connection, true);
                            if (existing != null)
                            {
                                if (this.m_settingsProvider.GetConfiguration().AutoUpdateExisting)
                                {
                                    this.m_tracer.TraceEvent(EventLevel.Warning, "INSERT WOULD RESULT IN DUPLICATE CLASSIFIER: UPDATING INSTEAD {0}", data);
                                    data.Key = existing.Key;
                                    data     = this.Update(connection, data);
                                }
                                else
                                {
                                    throw new DuplicateNameException(data.Key?.ToString());
                                }
                            }
                            else
                            {
                                this.m_tracer.TraceEvent(EventLevel.Verbose, "INSERT {0}", data);
                                data = this.Insert(connection, data);
                            }
                            data.LoadState = LoadState.FullLoad; // We just persisted so it is fully loaded

                            if (mode == TransactionMode.Commit)
                            {
                                tx.Commit();
                                var cacheService = ApplicationServiceContext.Current.GetService <IDataCachingService>();
                                cacheService?.Add(data);
                            }
                            else
                            {
                                tx.Rollback();
                            }

                            var args = new DataPersistedEventArgs <TData>(data, mode, overrideAuthContext);

                            this.Inserted?.Invoke(this, args);

                            return(data);
                        }
                        catch (DbException e)
                        {
#if DEBUG
                            this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0} -- {1}", e, this.ObjectToString(data));
#else
                            this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0}", e.Message);
#endif
                            tx?.Rollback();

                            throw new DataPersistenceException($"Error inserting {data}", this.TranslateDbException(e));
                        }
                    catch (DataPersistenceException)
                    {
                        throw;
                    }
                    catch (Exception e)
                    {
                        this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0} -- {1}", e, this.ObjectToString(data));

                        tx?.Rollback();
                        throw new DataPersistenceException(e.Message, e);
                    }
                    finally
                    {
                    }
                }
                finally
                {
                }
            }
        }
Esempio n. 28
0
        public DiagnosticReport Insert(DiagnosticReport storageData, TransactionMode mode, IPrincipal overrideAuthContext = null)
        {
            var persistenceArgs = new DataPersistingEventArgs <DiagnosticReport>(storageData, mode, overrideAuthContext);

            this.Inserting?.Invoke(this, persistenceArgs);
            if (persistenceArgs.Cancel)
            {
                this.m_traceSource.TraceEvent(EventLevel.Warning, "Pre-persistence event cancelled the insertion");
                return(persistenceArgs.Data);
            }

            try
            {
                // Send
                var serviceClient = new JiraServiceClient(new RestClient(this.m_configuration));

                serviceClient.Authenticate(new Model.JiraAuthenticationRequest(this.m_configuration.UserName, this.m_configuration.Password));
                var issue = serviceClient.CreateIssue(new Model.JiraIssueRequest()
                {
                    Fields = new Model.JiraIssueFields()
                    {
                        Description = storageData.Note,
                        Summary     = String.Format("SanteDB-DIAG: Issue from {0}", storageData?.Submitter?.Names?.FirstOrDefault()?.Component?.FirstOrDefault(n => n.ComponentTypeKey == NameComponentKeys.Given)?.Value),
                        IssueType   = new Model.JiraIdentifier("Bug"),
                        Priority    = new Model.JiraIdentifier("High"),
                        Project     = new Model.JiraKey(this.m_configuration.Project),
                        Labels      = new string[] { "SanteDBMobile" }
                    }
                });

                serviceClient.Client.Requesting += (o, e) =>
                {
                    e.AdditionalHeaders.Add("X-Atlassian-Token", "nocheck");
                };
                // Attachments
                List <MultipartAttachment> attachments = new List <MultipartAttachment>();

                foreach (var itm in storageData.Attachments)
                {
                    if (itm is DiagnosticBinaryAttachment)
                    {
                        var bin = itm as DiagnosticBinaryAttachment;
                        attachments.Add(new MultipartAttachment(bin.Content, "application/x-gzip", bin.FileDescription, true));
                    }
                    else
                    {
                        var txt = itm as DiagnosticTextAttachment;
                        attachments.Add(new MultipartAttachment(Encoding.UTF8.GetBytes(txt.Content), "text/plain", txt.FileName, true));
                    }
                }

                // Attach the application information
                using (var ms = new MemoryStream())
                {
                    XmlSerializer xsz = XmlModelSerializerFactory.Current.CreateSerializer(typeof(DiagnosticApplicationInfo));
                    xsz.Serialize(ms, storageData.ApplicationInfo);
                    attachments.Add(new MultipartAttachment(ms.ToArray(), "text/xml", "appinfo.xml", true));
                }
                serviceClient.CreateAttachment(issue, attachments);
                storageData.CorrelationId = issue.Key;
                storageData.Key           = Guid.NewGuid();

                // Invoke
                this.Inserted?.Invoke(this, new DataPersistedEventArgs <DiagnosticReport>(storageData, mode, overrideAuthContext));

                return(storageData);
            }
            catch (Exception ex)
            {
                this.m_traceSource.TraceEvent(EventLevel.Error, "Error sending to JIRA: {0}", ex);
                throw;
            }
        }
Esempio n. 29
0
        /// <summary>
        /// Update the specified object
        /// </summary>
        /// <param name="storageData"></param>
        /// <param name="principal"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public TData Update(TData data, TransactionMode mode, IPrincipal overrideAuthContext)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            else if (data.Key == Guid.Empty)
            {
                throw new InvalidOperationException("Data missing key");
            }

            DataPersistingEventArgs <TData> preArgs = new DataPersistingEventArgs <TData>(data, mode, overrideAuthContext);

            this.Updating?.Invoke(this, preArgs);
            if (preArgs.Cancel)
            {
                this.m_tracer.TraceEvent(EventLevel.Warning, "Pre-Event handler indicates abort update for {0}", data);
                return(data);
            }

            // Persist object
            using (var connection = this.m_settingsProvider.GetConfiguration().Provider.GetWriteConnection())
            {
                try
                {
                    connection.Open();
                    using (IDbTransaction tx = connection.BeginTransaction())
                        try
                        {
                            //connection.Connection.Open();

                            this.m_tracer.TraceEvent(EventLevel.Verbose, "UPDATE {0}", data);

                            connection.EstablishProvenance(overrideAuthContext, (data as NonVersionedEntityData)?.UpdatedByKey ?? (data as BaseEntityData)?.CreatedByKey);
                            data           = Update(connection, data);
                            data.LoadState = LoadState.FullLoad; // We just persisted this so it is fully loaded

                            if (mode == TransactionMode.Commit)
                            {
                                tx.Commit();
                                var cacheService = ApplicationServiceContext.Current.GetService <IDataCachingService>();
                                cacheService?.Remove(data);
                            }
                            else
                            {
                                tx.Rollback();
                            }

                            var args = new DataPersistedEventArgs <TData>(data, mode, overrideAuthContext);

                            this.Updated?.Invoke(this, args);

                            return(data);
                        }
                        catch (DbException e)
                        {
#if DEBUG
                            this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0} -- {1}", e, this.ObjectToString(data));
#else
                            this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0}", e.Message);
#endif
                            tx?.Rollback();

                            throw new DataPersistenceException($"Error updating {data}", this.TranslateDbException(e));
                        }
                    catch (Exception e)
                    {
#if DEBUG
                        this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0} -- {1}", e, this.ObjectToString(data));
#else
                        this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0}", e.Message);
#endif
                        tx?.Rollback();

                        // if the exception is key not found, we want the caller to know
                        // so that a potential insert can take place
                        if (e is KeyNotFoundException)
                        {
                            throw new KeyNotFoundException($"Record {data} was not found for update", e);
                        }

                        // if the exception is anything else, we want to throw a data persistence exception
                        throw new DataPersistenceException($"Error updating {data}", e);
                    }
                    finally
                    {
                    }
                }
                finally
                {
                }
            }
        }
Esempio n. 30
0
        /// <summary>
        /// Obsolete the specified key data
        /// </summary>
        /// <param name="storageData">The storage data to be obsoleted</param>
        /// <param name="principal">The principal to use to obsolete</param>
        /// <param name="mode">The mode of obsoletion</param>
        /// <returns>The obsoleted record</returns>
        public TModel Obsolete(TModel data, TransactionMode mode, IPrincipal principal)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            else if (data.Key == Guid.Empty)
            {
                throw new InvalidOperationException("Data missing key");
            }

            DataPersistingEventArgs <TModel> preArgs = new DataPersistingEventArgs <TModel>(data, mode, principal);

            this.Obsoleting?.Invoke(this, preArgs);
            if (preArgs.Cancel)
            {
                this.m_tracer.TraceWarning("Pre-Event handler indicates abort for {0}", data);
                return(data);
            }

            // Obsolete object
            using (var connection = AdoAuditPersistenceService.GetConfiguration().Provider.GetWriteConnection())
            {
                connection.Open();
                using (IDbTransaction tx = connection.BeginTransaction())
                    try
                    {
                        //connection.Connection.Open();

                        this.m_tracer.TraceVerbose("OBSOLETE {0}", data);
                        connection.EstablishProvenance(principal, (data as NonVersionedEntityData)?.ObsoletedByKey ?? (data as BaseEntityData)?.ObsoletedByKey);

                        data = this.ObsoleteInternal(connection, data, principal);
                        connection.AddCacheCommit(data);
                        if (mode == TransactionMode.Commit)
                        {
                            tx.Commit();
                            foreach (var itm in connection.CacheOnCommit)
                            {
                                ApplicationServiceContext.Current.GetService <IDataCachingService>()?.Remove(itm.Key.Value);
                            }
                        }
                        else
                        {
                            tx.Rollback();
                        }

                        var args = new DataPersistedEventArgs <TModel>(data, mode, principal);

                        this.Obsoleted?.Invoke(this, args);

                        return(data);
                    }
                    catch (Exception e)
                    {
                        this.m_tracer.TraceError("Error : {0}", e);
                        tx?.Rollback();
                        throw new DataPersistenceException(e.Message, e);
                    }
                finally
                {
                }
            }
        }