/// <summary> /// Get configuration /// </summary> public AdoPersistenceConfigurationSection GetConfiguration() { if (m_configuration == null) { m_configuration = ApplicationServiceContext.Current.GetService <IConfigurationManager>().GetSection <AdoPersistenceConfigurationSection>(); } return(m_configuration); }
/// <summary> /// ADO freetext constructor /// </summary> public AdoFreetextSearchService(IJobManagerService jobManager, IServiceManager serviceManager, IConfigurationManager configurationManager, IThreadPoolService threadPoolService) { this.m_configuration = configurationManager.GetSection <AdoPersistenceConfigurationSection>(); this.m_ftiRefreshThread = new Thread(this.MonitorFreetextJob) { Name = "ADO.NET FullText Realtime Refresh", IsBackground = true, Priority = ThreadPriority.Lowest }; this.m_ftiRefreshThread.Start(); if (this.m_configuration.Provider.GetFilterFunction("freetext") == null) { return; // Freetext not supported } var job = serviceManager.CreateInjected <AdoRebuildFreetextIndexJob>(); jobManager.AddJob(job, JobStartType.TimerOnly); if (jobManager.GetJobSchedules(job)?.Any() != true) { jobManager.SetJobSchedule(job, new DayOfWeek[] { DayOfWeek.Saturday }, new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0)); } // Subscribe to common types and events var appServiceProvider = ApplicationServiceContext.Current; appServiceProvider.GetService <IDataPersistenceService <Bundle> >().Inserted += (o, e) => e.Data.Item.ForEach(i => this.ReIndex(i)); appServiceProvider.GetService <IDataPersistenceService <Patient> >().Inserted += (o, e) => this.ReIndex(e.Data); appServiceProvider.GetService <IDataPersistenceService <Provider> >().Inserted += (o, e) => this.ReIndex(e.Data); appServiceProvider.GetService <IDataPersistenceService <Material> >().Inserted += (o, e) => this.ReIndex(e.Data); appServiceProvider.GetService <IDataPersistenceService <ManufacturedMaterial> >().Inserted += (o, e) => this.ReIndex(e.Data); appServiceProvider.GetService <IDataPersistenceService <Entity> >().Inserted += (o, e) => this.ReIndex(e.Data); appServiceProvider.GetService <IDataPersistenceService <Place> >().Inserted += (o, e) => this.ReIndex(e.Data); appServiceProvider.GetService <IDataPersistenceService <Organization> >().Inserted += (o, e) => this.ReIndex(e.Data); appServiceProvider.GetService <IDataPersistenceService <Person> >().Inserted += (o, e) => this.ReIndex(e.Data); appServiceProvider.GetService <IDataPersistenceService <Patient> >().Updated += (o, e) => this.ReIndex(e.Data); appServiceProvider.GetService <IDataPersistenceService <Provider> >().Updated += (o, e) => this.ReIndex(e.Data); appServiceProvider.GetService <IDataPersistenceService <Material> >().Updated += (o, e) => this.ReIndex(e.Data); appServiceProvider.GetService <IDataPersistenceService <ManufacturedMaterial> >().Updated += (o, e) => this.ReIndex(e.Data); appServiceProvider.GetService <IDataPersistenceService <Entity> >().Updated += (o, e) => this.ReIndex(e.Data); appServiceProvider.GetService <IDataPersistenceService <Place> >().Updated += (o, e) => this.ReIndex(e.Data); appServiceProvider.GetService <IDataPersistenceService <Organization> >().Updated += (o, e) => this.ReIndex(e.Data); appServiceProvider.GetService <IDataPersistenceService <Person> >().Updated += (o, e) => this.ReIndex(e.Data); appServiceProvider.Stopping += (o, e) => this.m_shutdown = true; }
/// <summary> /// Start the service and bind all of the sub-services /// </summary> public bool Start() { // Startup on system AuthenticationContext.Current = new AuthenticationContext(AuthenticationContext.SystemPrincipal); // notify startup this.Starting?.Invoke(this, EventArgs.Empty); if (this.m_running) return true; try { // Verify schema version using (DataContext mdc = this.GetConfiguration().Provider.GetReadonlyConnection()) { mdc.Open(); Version dbVer = new Version(mdc.FirstOrDefault<String>("get_sch_vrsn")), oizVer = typeof(AdoPersistenceService).Assembly.GetName().Version; if (oizVer < dbVer) throw new InvalidOperationException(String.Format("Invalid Schema Version. SanteDB version {0} is older than the database schema version {1}", oizVer, dbVer)); this.m_tracer.TraceInfo("SanteDB Schema Version {0} on {1}", dbVer, this.GetConfiguration().Provider.Invariant); } } catch (Exception e) { this.m_tracer.TraceEvent(EventLevel.Error, "Error starting ADO provider: {0}", e); throw; } // Iterate the persistence services foreach (var t in typeof(AdoPersistenceService).GetTypeInfo().Assembly.ExportedTypes.Where(o => o.Namespace == "SanteDB.Persistence.Data.ADO.Services.Persistence" && !o.GetTypeInfo().IsAbstract && !o.IsGenericTypeDefinition)) { try { this.m_tracer.TraceEvent(EventLevel.Informational, "Loading {0}...", t.AssemblyQualifiedName); // If the persistence service is generic then we should check if we're allowed if(!t.IsGenericType || t.IsGenericType && (this.GetConfiguration().AllowedResources.Count == 0 || this.GetConfiguration().AllowedResources.Contains(t.GetGenericArguments()[0].GetCustomAttribute<XmlTypeAttribute>()?.TypeName))) ApplicationServiceContext.Current.GetService<IServiceManager>().AddServiceProvider(t); // Add to cache since we're here anyways //s_persistenceCache.Add(t.GetGenericArguments()[0], Activator.CreateInstance(t) as IAdoPersistenceService); } catch (Exception e) { this.m_tracer.TraceEvent(EventLevel.Error, "Error adding service {0} : {1}", t.AssemblyQualifiedName, e); } } // Now iterate through the map file and ensure we have all the mappings, if a class does not exist create it try { this.m_tracer.TraceEvent(EventLevel.Informational, "Creating secondary model maps..."); var map = ModelMap.Load(typeof(AdoPersistenceService).GetTypeInfo().Assembly.GetManifestResourceStream(AdoDataConstants.MapResourceName)); foreach (var itm in map.Class) { // Is there a persistence service? var idpType = typeof(IDataPersistenceService<>); Type modelClassType = Type.GetType(itm.ModelClass), domainClassType = Type.GetType(itm.DomainClass); // Make sure we're allowed to run this if (this.GetConfiguration().AllowedResources.Count > 0 && !this.GetConfiguration().AllowedResources.Contains(modelClassType.GetCustomAttribute<XmlTypeAttribute>()?.TypeName)) continue; idpType = idpType.MakeGenericType(modelClassType); if (modelClassType.IsAbstract || domainClassType.IsAbstract) continue; // Already created if (ApplicationServiceContext.Current.GetService(idpType) != null) continue; this.m_tracer.TraceEvent(EventLevel.Verbose, "Creating map {0} > {1}", modelClassType, domainClassType); if (modelClassType.GetTypeInfo().ImplementedInterfaces.Contains(typeof(IBaseEntityData)) && domainClassType.GetTypeInfo().ImplementedInterfaces.Contains(typeof(IDbBaseData))) { // Construct a type Type pclass = null; if (modelClassType.GetTypeInfo().ImplementedInterfaces.Contains(typeof(IVersionedAssociation))) pclass = typeof(GenericBaseVersionedAssociationPersistenceService<,>); else if (modelClassType.GetTypeInfo().ImplementedInterfaces.Contains(typeof(ISimpleAssociation))) pclass = typeof(GenericBaseAssociationPersistenceService<,>); else pclass = typeof(GenericBasePersistenceService<,>); pclass = pclass.MakeGenericType(modelClassType, domainClassType); ApplicationServiceContext.Current.GetService<IServiceManager>().AddServiceProvider(pclass); // Add to cache since we're here anyways this.m_persistenceCache.Add(modelClassType, Activator.CreateInstance(pclass) as IAdoPersistenceService); } else if (modelClassType.GetTypeInfo().ImplementedInterfaces.Contains(typeof(IIdentifiedEntity)) && domainClassType.GetTypeInfo().ImplementedInterfaces.Contains(typeof(IDbIdentified))) { // Construct a type Type pclass = null; if (modelClassType.GetTypeInfo().ImplementedInterfaces.Contains(typeof(IVersionedAssociation))) pclass = typeof(GenericIdentityVersionedAssociationPersistenceService<,>); else if (modelClassType.GetTypeInfo().ImplementedInterfaces.Contains(typeof(ISimpleAssociation))) pclass = typeof(GenericIdentityAssociationPersistenceService<,>); else pclass = typeof(GenericIdentityPersistenceService<,>); pclass = pclass.MakeGenericType(modelClassType, domainClassType); ApplicationServiceContext.Current.GetService<IServiceManager>().AddServiceProvider(pclass); this.m_persistenceCache.Add(modelClassType, Activator.CreateInstance(pclass) as IAdoPersistenceService); } else this.m_tracer.TraceEvent(EventLevel.Warning, "Classmap {0}>{1} cannot be created, ignoring", modelClassType, domainClassType); } } catch (Exception e) { this.m_tracer.TraceEvent(EventLevel.Error, "Error initializing local persistence: {0}", e); throw e; } // Bind subscription execution ApplicationServiceContext.Current.GetService<IServiceManager>().AddServiceProvider(typeof(AdoSubscriptionExector)); // Bind BI stuff ApplicationServiceContext.Current.GetService<IBiMetadataRepository>()?.Insert(new SanteDB.BI.Model.BiDataSourceDefinition() { IsSystemObject = true, MetaData = new BiMetadata() { Version = typeof(AdoPersistenceService).Assembly.GetName().Version.ToString(), Status = BiDefinitionStatus.Active, }, Id = "org.santedb.bi.dataSource.main", Name = "main", ConnectionString = this.m_configuration.ReadonlyConnectionString, ProviderType = typeof(OrmBiDataProvider) }); // Bind some basic service stuff ApplicationServiceContext.Current.GetService<IDataPersistenceService<Core.Model.Security.SecurityUser>>().Inserting += (o, e) => { if (String.IsNullOrEmpty(e.Data.SecurityHash)) e.Data.SecurityHash = Guid.NewGuid().ToString(); }; ApplicationServiceContext.Current.GetService<IDataPersistenceService<Core.Model.Security.SecurityUser>>().Updating += (o, e) => { e.Data.SecurityHash = Guid.NewGuid().ToString(); }; // Unload configuration when app domain unloads ApplicationServiceContext.Current.Stopped += (o, e) => this.m_configuration = null; // Attempt to cache concepts this.m_tracer.TraceEvent(EventLevel.Verbose, "Caching concept dictionary..."); this.m_running = true; this.Started?.Invoke(this, EventArgs.Empty); return true; }
/// <summary> /// Creates a new DI injected policy manager /// </summary> public AdoRoleProvider(IConfigurationManager configurationManager, IPolicyEnforcementService pepService) { this.m_configuration = configurationManager.GetSection <AdoPersistenceConfigurationSection>(); this.m_policyService = pepService; }
/// <summary> /// DI constructor /// </summary> public AdoDeviceIdentityProvider(IConfigurationManager configurationManager, IPolicyEnforcementService pepService) { this.m_policyService = pepService; this.m_configuration = ApplicationServiceContext.Current.GetService <IConfigurationManager>().GetSection <AdoPersistenceConfigurationSection>(); }
/// <summary> /// Configure the service /// </summary> public void Configure(SanteDBConfiguration configuration, IDictionary <string, string> settings) { var configSection = configuration.GetSection <AdoPersistenceConfigurationSection>(); if (configSection == null) { configSection = new AdoPersistenceConfigurationSection() { AutoInsertChildren = true, AutoUpdateExisting = true, ProviderType = "Npgsql", ReadonlyConnectionString = "MAIN", ReadWriteConnectionString = "MAIN", UseFuzzyTotals = false, Validation = new EntityValidationFlags() { IdentifierFormat = true, IdentifierUniqueness = true, ValidationLevel = Core.BusinessRules.DetectedIssuePriorityType.Warning } }; configuration.AddSection(configSection); } if (settings.TryGetValue(ReadonlyConnectionSetting, out string roConnection)) { configSection.ReadonlyConnectionString = roConnection; } if (settings.TryGetValue(ConnectionStringSetting, out string rwConnection)) { configSection.ReadWriteConnectionString = rwConnection; } if (settings.TryGetValue(FuzzyTotalSetting, out string fuzzyTotal)) { if (!Boolean.TryParse(fuzzyTotal, out bool fuzzyTotalBool)) { throw new ArgumentException($"{fuzzyTotal} is not a valid Boolean"); } configSection.UseFuzzyTotals = fuzzyTotalBool; } // Service types var serviceTypes = new Type[] { typeof(SanteDB.Persistence.Data.ADO.Services.AdoApplicationIdentityProvider), typeof(SanteDB.Persistence.Data.ADO.Services.AdoDeviceIdentityProvider), typeof(SanteDB.Persistence.Data.ADO.Services.AdoIdentityProvider), typeof(SanteDB.Persistence.Data.ADO.Services.AdoSecurityChallengeProvider), typeof(SanteDB.Persistence.Data.ADO.Services.AdoSessionProvider), typeof(SanteDB.Persistence.Data.ADO.Services.AdoPolicyInformationService), typeof(SanteDB.Persistence.Data.ADO.Services.AdoRoleProvider), typeof(SanteDB.Persistence.Data.ADO.Services.AdoPersistenceService), typeof(SanteDB.Persistence.Data.ADO.Services.AdoSubscriptionExecutor), typeof(SanteDB.Persistence.Data.ADO.Services.AdoServiceFactory) }; // Add services var serviceConfiguration = configuration.GetSection <ApplicationServiceContextConfigurationSection>().ServiceProviders; serviceConfiguration.AddRange(serviceTypes.Where(t => !serviceConfiguration.Any(c => c.Type == t)).Select(t => new TypeReferenceConfiguration(t))); }
/// <summary> /// DI constructor /// </summary> public AdoRebuildFreetextIndexJob(IConfigurationManager configurationManager, IJobStateManagerService stateManagerService) { this.m_configuration = configurationManager.GetSection <AdoPersistenceConfigurationSection>(); this.m_stateManager = stateManagerService; }
/// <summary> /// DI constructor for ADO CHallenge /// </summary> public AdoSecurityChallengeProvider(IConfigurationManager configurationManager, IPolicyEnforcementService pepService) { this.m_policyEnforcementService = pepService; this.m_configuration = configurationManager.GetSection <AdoPersistenceConfigurationSection>(); this.m_securityConfiguration = configurationManager.GetSection <SecurityConfigurationSection>(); }
/// <summary> /// Start the service and bind all of the sub-services /// </summary> public bool Start() { // Startup on system using (AuthenticationContext.EnterSystemContext()) { // notify startup this.Starting?.Invoke(this, EventArgs.Empty); if (this.m_running) { return(true); } try { // Verify schema version using (DataContext mdc = this.GetConfiguration().Provider.GetReadonlyConnection()) { mdc.Open(); Version dbVer = new Version(mdc.ExecuteProcedure <String>("get_sch_vrsn")), oizVer = typeof(AdoPersistenceService).Assembly.GetName().Version; if (oizVer < dbVer) { throw new InvalidOperationException(String.Format("Invalid Schema Version. SanteDB version {0} is older than the database schema version {1}", oizVer, dbVer)); } this.m_tracer.TraceInfo("SanteDB Schema Version {0} on {1}", dbVer, this.GetConfiguration().Provider.Invariant); } } catch (Exception e) { this.m_tracer.TraceEvent(EventLevel.Error, "Error starting ADO provider: {0}", e); throw new InvalidOperationException("Could not start up ADO provider", e); } // Iterate the persistence services foreach (var t in typeof(AdoPersistenceService).Assembly.ExportedTypes.Where(o => o.Namespace == "SanteDB.Persistence.Data.ADO.Services.Persistence" && !o.IsAbstract && !o.IsGenericTypeDefinition)) { try { this.m_tracer.TraceEvent(EventLevel.Informational, "Loading {0}...", t.AssemblyQualifiedName); // If the persistence service is generic then we should check if we're allowed if (!t.IsGenericType || t.IsGenericType && (this.GetConfiguration().AllowedResources.Count == 0 || this.GetConfiguration().AllowedResources.Any(r => r.Type == t.GetGenericArguments()[0]))) { var instance = Activator.CreateInstance(t, this); ApplicationServiceContext.Current.GetService <IServiceManager>().AddServiceProvider(instance); } } catch (Exception e) { this.m_tracer.TraceEvent(EventLevel.Error, "Error adding service {0} : {1}", t.AssemblyQualifiedName, e); throw new InvalidOperationException($"Error adding service {t.AssemblyQualifiedName}", e); } } // Bind BI stuff ApplicationServiceContext.Current.GetService <IBiMetadataRepository>()?.Insert(new SanteDB.BI.Model.BiDataSourceDefinition() { IsSystemObject = true, MetaData = new BiMetadata() { Version = typeof(AdoPersistenceService).Assembly.GetName().Version.ToString(), Status = BiDefinitionStatus.Active, }, Id = "org.santedb.bi.dataSource.main", Name = "main", ConnectionString = this.m_configuration.ReadonlyConnectionString, ProviderType = typeof(OrmBiDataProvider) }); // Bind some basic service stuff ApplicationServiceContext.Current.GetService <IDataPersistenceService <Core.Model.Security.SecurityUser> >().Inserting += (o, e) => { if (String.IsNullOrEmpty(e.Data.SecurityHash)) { e.Data.SecurityHash = Guid.NewGuid().ToString(); } }; ApplicationServiceContext.Current.GetService <IDataPersistenceService <Core.Model.Security.SecurityUser> >().Updating += (o, e) => { e.Data.SecurityHash = Guid.NewGuid().ToString(); }; // Unload configuration when app domain unloads ApplicationServiceContext.Current.Stopped += (o, e) => this.m_configuration = null; // Attempt to cache concepts this.m_tracer.TraceEvent(EventLevel.Verbose, "Caching concept dictionary..."); this.m_running = true; this.Started?.Invoke(this, EventArgs.Empty); return(true); } }