public RestServiceConfiguration RetrieveCardPaymentServiceConfiguration(IOrganizationService organizationService, string configurationPrefix) { if (string.IsNullOrWhiteSpace(configurationPrefix)) { configurationPrefix = String.Empty; } // Read the settings IDictionary <string, string> configSettings = organizationService.GetConfigurationStringValues( $"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.ApiKey}", $"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.TargetUrl}", $"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.TargetHost}", $"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.SecurityProtocol}", $"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.SecurityHeader}"); // Parse the settings SecurityProtocolType protocolType; Enum.TryParse( configSettings[$"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.SecurityProtocol}"], out protocolType); RestServiceConfiguration config = new RestServiceConfiguration { ApiKey = configSettings[$"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.ApiKey}"], SecurityHeader = configSettings[$"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.SecurityHeader}"], SecurityProtocol = protocolType, TargetHost = configSettings[$"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.TargetHost}"], TargetUrl = configSettings[$"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.TargetUrl}"] }; return(config); }
/// <summary> /// Configure the setting /// </summary> /// <param name="configuration"></param> /// <param name="settings"></param> public void Configure(SanteDBConfiguration configuration, IDictionary <string, string> settings) { var metadataConf = configuration.GetSection <MetadataConfigurationSection>(); if (metadataConf == null) { metadataConf = new MetadataConfigurationSection(); configuration.AddSection(metadataConf); } var restConfiguration = configuration.GetSection <SanteDB.Rest.Common.Configuration.RestConfigurationSection>(); if (restConfiguration == null) { throw new ConfigurationException("Error retrieving REST configuration", configuration); } var openApiRestConfiguration = restConfiguration.Services.FirstOrDefault(o => o.ServiceType == typeof(IMetadataServiceContract)); if (openApiRestConfiguration == null) // add fhir rest config { openApiRestConfiguration = new RestServiceConfiguration() { Name = "META", Endpoints = new List <RestEndpointConfiguration>() { new RestEndpointConfiguration() { Address = "http://0.0.0.0:8080/api-docs", ContractXml = typeof(IMetadataServiceContract).AssemblyQualifiedName, } } }; restConfiguration.Services.Add(openApiRestConfiguration); } if (settings.TryGetValue(ListenSetting, out string listenStr)) { if (!Uri.TryCreate(listenStr, UriKind.Absolute, out Uri listenUri)) { throw new ArgumentException($"{listenStr} is not a valid URI"); } openApiRestConfiguration.Endpoints.ForEach(ep => ep.Address = listenStr); } // Client claims? if (settings.TryGetValue(ApiBaseSetting, out String baseSetting)) { restConfiguration.ExternalHostPort = baseSetting; } // Add services var serviceConfiguration = configuration.GetSection <ApplicationServiceContextConfigurationSection>().ServiceProviders; if (!serviceConfiguration.Any(s => s.Type == typeof(MetadataMessageHandler))) { serviceConfiguration.Add(new TypeReferenceConfiguration(typeof(MetadataMessageHandler))); } }
/// <summary> /// Query for the state of this rest service /// </summary> public FeatureInstallState QueryState(SanteDBConfiguration configuration) { // First, is the REST service enabled? if (!configuration.SectionTypes.Any(o => o.Type == typeof(RestConfigurationSection))) { configuration.AddSection(new RestConfigurationSection()); } // Does the contract exist? var restConfiguration = configuration.GetSection <RestConfigurationSection>().Services.FirstOrDefault(s => s.Endpoints.Any(e => e.Contract == this.m_contractType)); // Create / add section type if (!configuration.SectionTypes.Any(t => t.Type == this.m_configurationType)) { configuration.SectionTypes.Add(new TypeReferenceConfiguration(this.m_configurationType)); } // Does the section exist? var serviceConfiguration = configuration.GetSection(this.m_configurationType); // Feature state var featureState = serviceConfiguration != null && restConfiguration != null ? FeatureInstallState.Installed : serviceConfiguration != null ^ restConfiguration != null ? FeatureInstallState.PartiallyInstalled : FeatureInstallState.NotInstalled; // Do either exist? if (restConfiguration == null) { using (var s = this.m_configurationType.Assembly.GetManifestResourceStream(this.m_configurationType.Namespace + ".Default.xml")) restConfiguration = RestServiceConfiguration.Load(s); } if (serviceConfiguration == null) { serviceConfiguration = Activator.CreateInstance(this.m_configurationType); } // Construct the configuraiton this.Configuration = new GenericFeatureConfiguration() { Categories = new Dictionary <string, string[]>() { { "Misc", new string[] { "REST API", "Service" } } }, Options = new Dictionary <string, Func <object> >() { { "REST API", () => ConfigurationOptionType.Object }, { "Service", () => ConfigurationOptionType.Object } }, Values = new Dictionary <string, object>() { { "REST API", restConfiguration }, { "Service", serviceConfiguration } } }; return(featureState); }
/// <summary> /// Executes the WorkFlow. /// </summary> /// <param name="crmWorkflowContext">The <see cref="WorkFlowActivityBase.LocalWorkflowContext"/> which contains the /// <param name="executionContext" > <see cref="CodeActivityContext"/> /// </param> /// <remarks> /// For improved performance, Microsoft Dynamics 365 caches WorkFlow instances. /// The WorkFlow's Execute method should be written to be stateless as the constructor /// is not called for every invocation of the WorkFlow. Also, multiple system threads /// could execute the WorkFlow at the same time. All per invocation state information /// is stored in the context. This means that you should not use global variables in WorkFlows. /// </remarks> public override void ExecuteCRMWorkFlowActivity(CodeActivityContext executionContext, LocalWorkflowContext crmWorkflowContext) { var tracingService = executionContext.GetExtension <ITracingService>(); tracingService.Trace("CreatePayment starting..."); try { // 1. Validation ValidateNotNull(crmWorkflowContext); // 2. Prepare API Request tracingService.Trace("Calling PrepareCardPaymentRequest..."); CreatePaymentRequest apiRequest = this.PrepareCardPaymentRequest(executionContext); // 2. Retrieve Configuration tracingService.Trace("Calling RetrieveCardPaymentServiceConfiguration..."); RestServiceConfiguration cardServiceConfiguration = this.RetrieveCardPaymentServiceConfiguration(executionContext, ConfigurationPrefix.Get(executionContext)); // 3. Set-up the Api Service tracingService.Trace("Instantiating CardPaymentService..."); CardPaymentService cardPaymentService = new CardPaymentService(cardServiceConfiguration); // 4. Call the API tracingService.Trace("Calling GovPay CreatePayment with amount='{0}', description='{1}', reference='{2}', returnUrl='{3}'", apiRequest.amount, apiRequest.description, apiRequest.reference, apiRequest.return_url); CreatePaymentResponse apiResponse = cardPaymentService.CreatePayment(apiRequest); // TODO Log request and Response // 5. Return the response if (apiResponse != null && apiResponse.error_message != null) { tracingService.Trace("Error message: {0}", apiResponse.error_message); } tracingService.Trace("Calling PrepareOutputParameters..."); this.PrepareOutputParameters(executionContext, apiResponse, tracingService); } catch (Exception ex) { // Todo: Log the Error tracingService.Trace("Exception: " + ex); throw ex; } }
/// <summary> /// Executes the WorkFlow. /// </summary> /// <param name="crmWorkflowContext">The <see cref="WorkFlowActivityBase.LocalWorkflowContext"/> which contains the /// <param name="executionContext" > <see cref="CodeActivityContext"/> /// </param> /// <remarks> /// For improved performance, Microsoft Dynamics 365 caches WorkFlow instances. /// The WorkFlow's Execute method should be written to be stateless as the constructor /// is not called for every invocation of the WorkFlow. Also, multiple system threads /// could execute the WorkFlow at the same time. All per invocation state information /// is stored in the context. This means that you should not use global variables in WorkFlows. /// </remarks> public override void ExecuteCRMWorkFlowActivity(CodeActivityContext executionContext, LocalWorkflowContext crmWorkflowContext) { var tracingService = executionContext.GetExtension <ITracingService>(); tracingService.Trace("FindPayment starting..."); try { // 1. Validation ValidateNotNull(crmWorkflowContext); // 2. Prepare API Request tracingService.Trace("Calling PrepareFindPaymentRequest..."); FindPaymentRequest apiRequest = this.PrepareFindPaymentRequest(executionContext, crmWorkflowContext, tracingService); // 3. Retrieve Configuration tracingService.Trace("Calling RetrieveCardPaymentServiceConfiguration..."); RestServiceConfiguration cardServiceConfiguration = this.RetrieveCardPaymentServiceConfiguration(executionContext, ConfigurationPrefix.Get(executionContext)); // 4. Set-up the Api Service tracingService.Trace("Instantiating CardPaymentService..."); CardPaymentService cardPaymentService = new CardPaymentService(cardServiceConfiguration); // 5. Call the API tracingService.Trace("Calling GovPay FindPayment..."); FindPaymentResponse apiResponse = cardPaymentService.FindPayment(apiRequest); // 6. Return the response tracingService.Trace("Calling PrepareOutputParameters..."); this.PrepareOutputParameters(executionContext, apiResponse, tracingService); } catch (Exception ex) { // Todo: Log the Error tracingService.Trace("Exception: " + ex); throw ex; } }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "DavidMorales.WebHost v1")); app.UseDeveloperExceptionPage(); app.UseCors(builder => { builder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); }); } else { //app.UseExceptionHandler("/Error"); app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "DavidMorales.WebHost v1")); app.UseDeveloperExceptionPage(); app.UseCors(builder => { builder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); }); } RestServiceConfiguration.Configure(app); DatabaseConfiguration.Configure(app); IdentityServiceConfiguration.Configure(app); AuthenticationConfiguration.Configure(app); AppAuthorizationConfiguration.Configure(app); }
protected RestServiceConfiguration RetrieveCardPaymentServiceConfiguration(CodeActivityContext executionContext, string configurationPrefix) { if (string.IsNullOrWhiteSpace(configurationPrefix)) { configurationPrefix = String.Empty; } IOrganizationServiceFactory factory = (IOrganizationServiceFactory)executionContext.GetExtension <IOrganizationServiceFactory>(); IOrganizationService service = factory.CreateOrganizationService(null); // Read the settings IDictionary <string, string> configSettings = service.GetConfigurationStringValues( $"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.ApiKey}", $"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.TargetUrl}", $"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.TargetHost}", $"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.SecurityProtocol}", $"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.SecurityHeader}"); // Parse the settings SecurityProtocolType protocolType; Enum.TryParse( configSettings[$"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.SecurityProtocol}"], out protocolType); RestServiceConfiguration config = new RestServiceConfiguration { ApiKey = configSettings[$"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.ApiKey}"], SecurityHeader = configSettings[$"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.SecurityHeader}"], SecurityProtocol = protocolType, TargetHost = configSettings[$"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.TargetHost}"], TargetUrl = configSettings[$"{configurationPrefix}{CardPaymentServiceSecureConfigurationKeys.TargetUrl}"] }; return(config); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { // Api Rest Configuration RestServiceConfiguration.ConfigureServices(services); // Database configuration DatabaseConfiguration.ConfigureServices(services, Configuration); // Identity service configuration IdentityServiceConfiguration.ConfigureServices(services, Configuration); // Authorization AppAuthorizationConfiguration.ConfigureAuthorization(services); // Authentication configuration AuthenticationConfiguration.ConfigureServices(services, Configuration); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "DavidMorales.WebHost", Version = "v1" }); }); // Identity services.AddTransient <AppIdentity>(); services.TryAddSingleton <IHttpContextAccessor, HttpContextAccessor>(); // Log services.AddLogging(); // Cors services.AddCors(); }
/// <summary> /// Configure /// </summary> /// <param name="configuration"></param> /// <param name="settings"></param> public void Configure(SanteDBConfiguration configuration, IDictionary <string, string> settings) { var oauthConf = configuration.GetSection <OAuthConfigurationSection>(); if (oauthConf == null) { oauthConf = DockerFeatureUtils.LoadConfigurationResource <OAuthConfigurationSection>("SanteDB.Authentication.OAuth2.Docker.OauthFeature.xml"); configuration.AddSection(oauthConf); } var restConfiguration = configuration.GetSection <SanteDB.Rest.Common.Configuration.RestConfigurationSection>(); if (restConfiguration == null) { throw new ConfigurationException("Error retrieving REST configuration", configuration); } var oauthRestConfiguration = restConfiguration.Services.FirstOrDefault(o => o.ServiceType == typeof(IOAuthTokenContract)); if (oauthRestConfiguration == null) // add fhir rest config { oauthRestConfiguration = new RestServiceConfiguration() { Name = "OAuth2", Endpoints = new List <RestEndpointConfiguration>() { new RestEndpointConfiguration() { Address = "http://0.0.0.0:8080/auth", ContractXml = typeof(IOAuthTokenContract).AssemblyQualifiedName, } } }; restConfiguration.Services.Add(oauthRestConfiguration); } if (settings.TryGetValue(ListenSetting, out string listenStr)) { if (!Uri.TryCreate(listenStr, UriKind.Absolute, out Uri listenUri)) { throw new ArgumentException($"{listenStr} is not a valid URI"); } oauthRestConfiguration.Endpoints.ForEach(ep => ep.Address = listenStr); } // Client claims? if (settings.TryGetValue(ClientClaimSetting, out String claim)) { oauthConf.AllowedClientClaims = claim.Split(';').ToList(); } // Token type? if (settings.TryGetValue(TokenTypeSetting, out String tokenType)) { oauthConf.TokenType = tokenType; } // Allow insecure authentication? if (settings.TryGetValue(NodelessClientAuthSetting, out string insecureSetting)) { if (!bool.TryParse(insecureSetting, out bool insecureBool)) { throw new ArgumentOutOfRangeException($"{insecureSetting} is not a valid boolean value"); } oauthConf.AllowClientOnlyGrant = insecureBool; } // Issuer (used for client claims auth and oauth) if (settings.TryGetValue(IssuerIdSetting, out String issuer)) { oauthConf.IssuerName = issuer; } if (settings.TryGetValue(JwtSigningKey, out String jwtSinging)) { oauthConf.JwtSigningKey = jwtSinging; } // Add services var serviceConfiguration = configuration.GetSection <ApplicationServiceContextConfigurationSection>().ServiceProviders; if (!serviceConfiguration.Any(s => s.Type == typeof(OAuthMessageHandler))) { serviceConfiguration.Add(new TypeReferenceConfiguration(typeof(OAuthMessageHandler))); } }
/// <summary> /// Configure the service /// </summary> public void Configure(SanteDBConfiguration configuration, IDictionary <string, string> settings) { var restConfiguration = configuration.GetSection <SanteDB.Rest.Common.Configuration.RestConfigurationSection>(); if (restConfiguration == null) { throw new ConfigurationException("Error retrieving REST configuration", configuration); } var fhirRestConfiguration = restConfiguration.Services.FirstOrDefault(o => o.ServiceType == typeof(IFhirServiceContract)); if (fhirRestConfiguration == null) // add fhir rest config { fhirRestConfiguration = new RestServiceConfiguration() { Behaviors = new List <RestServiceBehaviorConfiguration>() { new RestServiceBehaviorConfiguration(typeof(TokenAuthorizationAccessBehavior)) }, Name = "FHIR", Endpoints = new List <RestEndpointConfiguration>() { this.CreateEndpoint("http://0.0.0.0:8080/fhir") } }; RestServiceConfiguration.Load(typeof(IFhirServiceContract).Assembly.GetManifestResourceStream("SanteDB.Messaging.FHIR.Configuration.Default.xml")); restConfiguration.Services.Add(fhirRestConfiguration); } var fhirConfiguration = configuration.GetSection <FhirServiceConfigurationSection>(); if (fhirConfiguration == null) { fhirConfiguration = new FhirServiceConfigurationSection() { ResourceBaseUri = "http://127.0.0.1:8080/fhir", ResourceHandlers = typeof(FhirDockerFeature).Assembly.ExportedTypes.Where(o => typeof(IFhirResourceHandler).IsAssignableFrom(o) && !o.IsAbstract && o.IsClass).Select(o => new TypeReferenceConfiguration(o)).ToList() }; configuration.AddSection(fhirConfiguration); } // Listen address if (settings.TryGetValue(ListenUriSetting, out string listen)) { if (!Uri.TryCreate(listen, UriKind.Absolute, out Uri listenUri)) { throw new ArgumentOutOfRangeException($"{listen} is not a valid URL"); } // Setup the endpoint fhirRestConfiguration.Endpoints.Clear(); fhirRestConfiguration.Endpoints.Add(new RestEndpointConfiguration() { Address = listen, ContractXml = typeof(IFhirServiceContract).AssemblyQualifiedName, Behaviors = new List <RestEndpointBehaviorConfiguration>() { new RestEndpointBehaviorConfiguration(typeof(MessageLoggingEndpointBehavior)), new RestEndpointBehaviorConfiguration(typeof(MessageCompressionEndpointBehavior)), new RestEndpointBehaviorConfiguration(typeof(AcceptLanguageEndpointBehavior)) } }); } // Authentication if (settings.TryGetValue(AuthenticationSetting, out string auth)) { if (!this.authSettings.TryGetValue(auth.ToUpperInvariant(), out Type authType)) { throw new ArgumentOutOfRangeException($"Don't understand auth option {auth} allowed values {String.Join(",", this.authSettings.Keys)}"); } // Add behavior if (authType != null) { fhirRestConfiguration.Behaviors.Add(new RestServiceBehaviorConfiguration() { Type = authType }); } else { fhirRestConfiguration.Behaviors.RemoveAll(o => this.authSettings.Values.Any(v => v == o.Type)); } } // Has the user set CORS? if (settings.TryGetValue(CorsSetting, out string cors)) { if (!Boolean.TryParse(cors, out bool enabled)) { throw new ArgumentOutOfRangeException($"{cors} is not a valid boolean value"); } // Cors is disabled? if (!enabled) { fhirRestConfiguration.Endpoints.ForEach(ep => ep.Behaviors.RemoveAll(o => o.Type == typeof(CorsEndpointBehavior))); } else { fhirRestConfiguration.Endpoints.ForEach(ep => ep.Behaviors.RemoveAll(o => o.Type == typeof(CorsEndpointBehavior))); fhirRestConfiguration.Endpoints.ForEach(ep => ep.Behaviors.Add(new RestEndpointBehaviorConfiguration() { Type = typeof(CorsEndpointBehavior) })); } } // Base URI if (settings.TryGetValue(BaseUriSetting, out string baseUri)) { fhirConfiguration.ResourceBaseUri = baseUri; } // Custom resource list? if (settings.TryGetValue(ResourceSetting, out string resource)) { fhirConfiguration.Resources = new List <string>(); foreach (var res in resource.Split(';')) { if (!Enum.TryParse <Hl7.Fhir.Model.ResourceType>(res, out Hl7.Fhir.Model.ResourceType rt)) { throw new ArgumentOutOfRangeException($"{res} is not a valid FHIR resource"); } // Add resource setting fhirConfiguration.Resources.Add(res); } } // Custom operation list? if (settings.TryGetValue(OperationSetting, out string operations)) { fhirConfiguration.Operations = new List <string>(); foreach (var res in operations.Split(';')) { fhirConfiguration.Operations.Add(res); } } // Custom profile list? if (settings.TryGetValue(ProfileSetting, out string profiles)) { fhirConfiguration.Profiles = new List <string>(); foreach (var res in profiles.Split(';')) { fhirConfiguration.Profiles.Add(res); } } // Custom settings if (settings.TryGetValue(ExtensionSetting, out string extensions)) { fhirConfiguration.Extensions = new List <string>(); foreach (var res in extensions.Split(';')) { fhirConfiguration.Extensions.Add(res); } } // Custom message list? if (settings.TryGetValue(MessageSetting, out string messages)) { fhirConfiguration.Messages = new List <string>(); foreach (var res in messages.Split(';')) { fhirConfiguration.Messages.Add(res); } } // Add services var serviceConfiguration = configuration.GetSection <ApplicationServiceContextConfigurationSection>().ServiceProviders; if (!serviceConfiguration.Any(s => s.Type == typeof(FhirMessageHandler))) { serviceConfiguration.Add(new TypeReferenceConfiguration(typeof(FhirMessageHandler))); serviceConfiguration.Add(new TypeReferenceConfiguration(typeof(FhirDataInitializationService))); } }
public CardPaymentService(RestServiceConfiguration configuration) : base(configuration) { }