/// <summary> /// Execute handler /// </summary> /// <typeparam name="TResult"></typeparam> /// <param name="process"></param> /// <param name="processType"></param> /// <param name="args"></param> /// <returns></returns> public TResult Execute <TResult>(IBaseProcess <TResult> process, Type processType, params object[] args) where TResult : VoidResult, new() { var strategyHandler = SystemBootstrapper.GetInstance <IStrategyHandler>(); if (strategyHandler.IsNull() || !strategyHandler.AutoHandleErrorProcesses) { try { return(Next.Execute(process, processType, args)); } catch (Exception ex) { return(VoidResult.FaultedResult <TResult>(ex)); } } var strategyResult = strategyHandler.Execute(() => Next.Execute(process, processType, args)); if (strategyResult.Exception != null) { return(VoidResult.FaultedResult <TResult>(strategyResult.Exception)); } return(strategyResult.Result); }
/// <summary> /// Handle process result /// </summary> /// <typeparam name="TProcess"></typeparam> /// <param name="process"></param> /// <param name="type"></param> /// <param name="response"></param> /// <param name="context"></param> /// <returns></returns> public MiddlewareResult HandleAfterExecution <TProcess>(TProcess process, Type type, VoidResult response, IHttpContextWrapper context) where TProcess : IBaseProcess <VoidResult> { var headers = SystemBootstrapper.GetInstance <List <ResponseHeaderAttribute> >(); headers.ForEach(header => { foreach (var responseHeader in header.Headers) { context.Headers.AddToResponse(responseHeader.Key, responseHeader.Value); } }); var headerAttribute = type .GetCustomAttributes(true) .Where(x => x.GetType() == typeof(ResponseHeaderAttribute) || x.GetType().IsSubclassOf(typeof(ResponseHeaderAttribute))) .Cast <ResponseHeaderAttribute>() .ToList(); headerAttribute.ForEach(header => { foreach (var responseHeader in header.Headers) { context.Headers.AddToResponse(responseHeader.Key, responseHeader.Value); } }); return(MiddlewareResult.DoNothing); }
/// <summary> /// Register background tasks /// </summary> private static void RegisterBackground() { var channel = SystemBootstrapper.GetInstance <IMessageChannel>(); if (!channel.IsNull()) { var processRepo = SystemBootstrapper.GetInstance <ProcessRepository>(); processRepo.OfType <IDistributedProcess>().ForEach(type => { channel.Subscribe <string>(type.Name, message => { var meta = message.Deserialize <DistributedProcessMetadata>(); var executor = SystemBootstrapper.GetInstance <IProcessExecutor>(); var instance = SystemBootstrapper.GetInstance(type) as IBaseProcess <VoidResult>; SystemBootstrapper.Bootstrap(instance); instance.EpicId = meta.EpicId; instance.CallerProcessName = meta.CallerProcessName; Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = new CultureInfo(meta.CultureName); executor.ExecuteBackground(instance, meta.Payload); }); }); } }
/// <summary> /// Authentication callback /// </summary> /// <returns></returns> internal bool Authenticate() { return(SystemBootstrapper.GetInstance <IAuthenticationManager>()? .GetCurrentPrincipal()? .Identity? .IsAuthenticated == true); }
/// <summary> /// CTOR /// </summary> /// <param name="faultMessage"></param> /// <param name="translateFaultMessage"></param> public GeneralErrorInfo(string faultMessage, bool translateFaultMessage = true) { var localizer = SystemBootstrapper.GetInstance <ILocalizationProvider>(); FaultMessage = faultMessage; UserVisibleMessage = translateFaultMessage ? localizer?.Get(faultMessage)?.Value ?? null : null; }
/// <summary> /// Write response /// </summary> /// <param name="httpResponse"></param> /// <returns></returns> public void PutResponse(HttpResponseMessage httpResponse) { var contextAccessor = _httpContextAccessor ?? SystemBootstrapper.GetInstance <IHttpContextAccessor>(); var context = _httpContextAccessor.HttpContext; if (httpResponse?.Headers?.Any() == true) { foreach (var header in httpResponse?.Headers) { context.Response.Headers.Add(header.Key, new StringValues(header.Value.ToArray())); } } if (httpResponse?.Content?.Headers?.Any() == true) { foreach (var header in httpResponse?.Content?.Headers) { context.Response.Headers.Add(header.Key, new StringValues(header.Value.ToArray())); } } context.Response.StatusCode = (int)httpResponse.StatusCode; if (!httpResponse.Content.IsNull()) { var body = httpResponse.Content.ReadAsStreamAsync().Result; body.CopyToAsync(context.Response.Body).Wait(); body.Close(); } }
/// <summary> /// CTOR /// </summary> /// <param name="faultMessage"></param> /// <param name="httpStatusCode"></param> /// <param name="translateFaultMessage"></param> public CodeSpecificErrorInfo(string faultMessage, HttpStatusCode httpStatusCode, bool translateFaultMessage = true) { var localizer = SystemBootstrapper.GetInstance <ILocalizationProvider>(); FaultMessage = faultMessage; UserVisibleMessage = translateFaultMessage ? localizer?.Get(faultMessage)?.Value ?? null : null; HttpStatusCode = httpStatusCode; }
public void MyService_WhenInjected_ReturnsValue() { var service = new RegistrationService(); SystemBootstrapper.Init(service, typeof(DotNetCoreTests).Assembly); SystemBootstrapper.Bootstrap(this); Assert.Equal(3, MyService1.Add(1, 2)); }
/// <summary> /// CTOR /// </summary> /// <param name="exception"></param> public UnmanagedExceptionErrorInfo(Exception exception) { Exception = exception; FaultMessage = exception.Message; var localizer = SystemBootstrapper.GetInstance <ILocalizationProvider>(); UserVisibleMessage = localizer?.Get("SystemError")?.Value ?? "Something happened!"; }
/// <summary> /// <see cref="ISyncTask"/> execution handle /// </summary> public void Execute() { var factor = SystemBootstrapper.GetInstance <IProcessFactory>(); var executor = SystemBootstrapper.GetInstance <IProcessExecutor>(); var instance = factor.Create <VoidResult>(InnerProcessType); executor.Execute(instance); }
public void MyService_WhenRegistered_InstantiatedAsInterface_ReturnsValue() { var service = new RegistrationService(); SystemBootstrapper.Init(service, typeof(DotNetCoreTests).Assembly); var srv = SystemBootstrapper.GetInstance <IMyService1>(); Assert.Equal(3, srv.Add(1, 2)); }
/// <summary> /// Inject all properties and fields annotated with <see cref="ImportAttribute"/> /// </summary> /// <param name="obj"></param> /// <param name="recursive"></param> private void InjectInternal(object obj, bool recursive) { if (obj == null) { return; } if (obj is IEnumerable) { return; } var type = obj.GetType(); var assemblyName = type.Assembly.FullName; if (assemblyName.StartsWith("System")) { return; } if (assemblyName.StartsWith("Microsoft")) { return; } // public and private properties and fields var injectables = GetInjectables(type); foreach (var injectable in injectables) { var instance = SystemBootstrapper.GetInstance(injectable.PropertyType); if (instance != null) { injectable.SetValue(obj, instance); } } if (recursive) { var fields = GetFields(type); var properties = GetProperties(type); // Recursively inject instances of child properties to all properties foreach (var property in properties) { InjectInternal(property.GetValue(obj), recursive); } // Recursively inject instances of child properties to all fields foreach (var field in fields) { InjectInternal(field.GetValue(obj), recursive); } } }
public void MyService_WhenRegistered_InstantiatedAsConcrete_ReturnsValue() { var service = new RegistrationService(); service.Register <MyService1>(); SystemBootstrapper.Init(service, typeof(SimpleInjectorTests).Assembly); var srv = SystemBootstrapper.GetInstance <MyService1>(); Assert.Equal(3, srv.Add(1, 2)); }
/// <summary> /// CTOR /// </summary> public WebMediator() { // Order is important CustomUrlHandlers = new List <ICustomUrlHandler> { new DocsHandler() }; // order is not important Filters = new List <IFilter> { new TypeFilter(), new HttpMethodFilter(), new RouteFilter() }; // order is not important FactoryFilters = new List <IFactoryFilter> { new IsCachedFactoryFilter() }; DefaultModelBinders = new Dictionary <SignalsApiMethod, BaseModelBinder> { { SignalsApiMethod.OPTIONS, new FromQuery() }, { SignalsApiMethod.GET, new FromQuery() }, { SignalsApiMethod.HEAD, new FromHeader() }, { SignalsApiMethod.POST, new FromBody() }, { SignalsApiMethod.PUT, new FromBody() }, { SignalsApiMethod.DELETE, new FromQuery() } }; // order is important, JsonResult is default fallback ResultHandlers = new List <IResultHandler> { new HeaderAdderHandler(), new AuthenticationFailResultFilter(), new AuthorizationFailResultFilter(), new UnmanagedFailResultFilter(), new SpecificationFailResultFilter(), new CodeSpecificFailResultFilter(), new GeneralFailResultFilter(), new CacheResultHandler(), new FileResultHandler(), new XmlResultHandler(), new NativeResultHandler(), new JsonResultHandler() }; // get process repo instance ProcessRepository = SystemBootstrapper.GetInstance <ProcessRepository>(); ProcessFactory = SystemBootstrapper.GetInstance <IProcessFactory>(); ProcessExecutor = SystemBootstrapper.GetInstance <IProcessExecutor>(); }
/// <summary> /// .Net core middleware registration extension /// </summary> /// <param name="app"></param> /// <returns></returns> public static IApplicationBuilder UseSignals(this IApplicationBuilder app) { var mediator = SystemBootstrapper.GetInstance <WebMediator>(); // mediator middleware return(app.Use(async(httpContext, next) => { if (mediator.Dispatch() != MiddlewareResult.StopExecutionAndStopMiddlewarePipe) { await next(); } })); }
/// <summary> /// Append docs to http response /// </summary> /// <param name="context"></param> /// <returns></returns> public MiddlewareResult RenderContent(IHttpContextWrapper context) { if (!context.RawUrl.ToLowerInvariant().Contains("api/spec")) { return(MiddlewareResult.DoNothing); } var cache = SystemBootstrapper.GetInstance <ICache>(); var cacheKey = "cache:api/spec"; OpenApiDocument docs; var cachedDocs = cache.Get <OpenApiDocument>(cacheKey); if (cachedDocs.IsNull()) { docs = GenerateDocs(); cache.Set(new CacheEntry(cacheKey, docs) { ExpirationTime = TimeSpan.FromDays(10000), ExpirationPolicy = CacheExpirationPolicy.Sliding }); } else { docs = cachedDocs; } string docsString; string contentType; if (context.RawUrl.ToLowerInvariant().EndsWith(".yaml")) { docsString = docs.Serialize(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Yaml); contentType = "text/x-yaml"; } else { docsString = docs.Serialize(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Json); contentType = "application/json"; } context.PutResponse(new HttpResponseMessage { Content = new StringContent(docsString, System.Text.Encoding.UTF8, contentType) }); return(MiddlewareResult.StopExecutionAndStopMiddlewarePipe); }
/// <summary> /// Handle process result /// </summary> /// <typeparam name="TProcess"></typeparam> /// <param name="process"></param> /// <param name="type"></param> /// <param name="response"></param> /// <param name="context"></param> /// <returns></returns> public MiddlewareResult HandleAfterExecution <TProcess>(TProcess process, Type type, VoidResult response, IHttpContextWrapper context) where TProcess : IBaseProcess <VoidResult> { if (!response.IsFaulted) { var cacheAttribute = type.GetCustomAttributes(typeof(OutputCacheAttribute), true).Cast <OutputCacheAttribute>().SingleOrDefault(); if (cacheAttribute != null && (cacheAttribute.Location == CacheLocation.Server || cacheAttribute.Location == CacheLocation.ClientAndServer)) { var cache = SystemBootstrapper.GetInstance <ICache>(); if (cache != null) { var key = type.FullName; if (!cacheAttribute.VaryByQueryParams.IsNullOrHasZeroElements()) { var queryValues = context ?.Query ?.Where(x => cacheAttribute.VaryByQueryParams.Contains(x.Key)) ?.OrderBy(x => x.Key) ?.Select(x => x.Value) ?.SerializeJson(); if (!queryValues.IsNullOrEmpty()) { key = $"{type.FullName}+{queryValues}"; } } var entry = cache.Get(key); if (entry.IsNull()) { cache.Set(new CacheEntry(key, response) { ExpirationTime = TimeSpan.FromSeconds(cacheAttribute.Duration), ExpirationPolicy = CacheExpirationPolicy.Absolute }); } } } if (cacheAttribute != null && (cacheAttribute.Location == CacheLocation.Client || cacheAttribute.Location == CacheLocation.ClientAndServer)) { context.Headers.AddToResponse("Cache-Control", $"max-age={cacheAttribute.Duration}, public"); } } return(MiddlewareResult.DoNothing); }
/// <summary> /// Validates instance /// </summary> /// <typeparam name="TProcess"></typeparam> /// <param name="instance"></param> /// <param name="type"></param> /// <param name="context"></param> /// <returns>Is instance valid</returns> public MiddlewareResult IsValidInstance <TProcess>(TProcess instance, Type type, IHttpContextWrapper context) where TProcess : IBaseProcess <VoidResult> { var cacheAttribute = type.GetCustomAttributes(typeof(OutputCacheAttribute), true).Cast <OutputCacheAttribute>().SingleOrDefault(); if (cacheAttribute != null && (cacheAttribute.Location == CacheLocation.Server || cacheAttribute.Location == CacheLocation.ClientAndServer)) { var cache = SystemBootstrapper.GetInstance <ICache>(); if (cache != null) { var key = type.FullName; if (!cacheAttribute.VaryByQueryParams.IsNullOrHasZeroElements()) { var queryValues = context ?.Query ?.Where(x => cacheAttribute.VaryByQueryParams.Contains(x.Key)) ?.OrderBy(x => x.Key) ?.Select(x => x.Value) ?.SerializeJson(); if (!queryValues.IsNullOrEmpty()) { key = $"{type.FullName}+{queryValues}"; } } var entry = cache.Get(key); if (!entry.IsNull()) { var webMediator = SystemBootstrapper.GetInstance <WebMediator>(); var httpContext = SystemBootstrapper.GetInstance <IHttpContextWrapper>(); foreach (var executeEvent in webMediator.ResultHandlers) { var result = executeEvent.HandleAfterExecution(instance, type, (VoidResult)entry.Value, httpContext); if (result != MiddlewareResult.DoNothing) { return(result); } } } } } return(MiddlewareResult.DoNothing); }
/// <summary> /// Schedule recurring tasks /// </summary> private static void ScheduleRecurring() { var bgRegistry = SystemBootstrapper.GetInstance <ITaskRegistry>(); if (!bgRegistry.IsNull()) { var processRepo = SystemBootstrapper.GetInstance <ProcessRepository>(); processRepo.OfType <IRecurringProcess>().ForEach(type => { var instance = SystemBootstrapper.GetInstance(type) as IRecurringProcess; var task = new RecurringTaskWrapper(type); bgRegistry.ScheduleTask(task, instance.Profile); }); bgRegistry.Start(); } }
/// <summary> /// CTOR /// </summary> /// <param name="specificaitonResult"></param> public SpecificationErrorInfo(SpecificationResult specificaitonResult) { if (!specificaitonResult.IsValid) { FaultMessage = specificaitonResult.Input.IsNull() ? $"Specificaiton {specificaitonResult.SpecificationType.Name} failed" : $"Specificaiton {specificaitonResult.SpecificationType.Name} failed for input {specificaitonResult.Input.GetType().Name} with payload {specificaitonResult.Input.SerializeJson()}"; var localizer = SystemBootstrapper.GetInstance <ILocalizationProvider>(); if (!localizer.IsNull()) { var specificaitonName = specificaitonResult.SpecificationType.Name; var parametarlessName = specificaitonName.Split('`')[0]; UserVisibleMessage = localizer?.Get(parametarlessName)?.Value; } } }
/// <summary> /// Execute handler /// </summary> /// <typeparam name="TResult"></typeparam> /// <param name="process"></param> /// <param name="processType"></param> /// <param name="args"></param> /// <returns></returns> public TResult Execute <TResult>(IBaseProcess <TResult> process, Type processType, params object[] args) where TResult : VoidResult, new() { var auditProvider = SystemBootstrapper.GetInstance <IAuditProvider>(); if (auditProvider.IsNull()) { return(Next.Execute(process, processType, args)); } var entry = auditProvider.Entry(); entry.Originator = ApplicationConfiguration.Instance?.ApplicationName ?? Environment.MachineName; entry.Process = process.Name; entry.EventType = process.Description; entry.EpicId = process.EpicId; entry.Payload = args?.SerializeJson(); return(auditProvider.Audit(entry, () => Next.Execute(process, processType, args))); }
/// <summary> /// Execute handler /// </summary> /// <typeparam name="TResult"></typeparam> /// <param name="process"></param> /// <param name="processType"></param> /// <param name="args"></param> /// <returns></returns> public TResult Execute <TResult>(IBaseProcess <TResult> process, Type processType, params object[] args) where TResult : VoidResult, new() { var innerResult = Next.Execute(process, processType, args); var logger = SystemBootstrapper.GetInstance <ILogger>(); if (logger.IsNull()) { return(innerResult); } if (innerResult.IsFaulted) { if (innerResult.IsSystemFault) { var errorInfo = innerResult.ErrorMessages.OfType <UnmanagedExceptionErrorInfo>().SingleOrDefault(); var exception = errorInfo.Exception; var entry = LogEntry.Exception(exception, message: innerResult.GetFaultMessage()); entry.ProcessName = process.Name; entry.Action = exception.TargetSite?.Name; entry.Origin = ApplicationConfiguration.Instance?.ApplicationName ?? Environment.MachineName; entry.Payload = args?.SerializeJson(); entry.UserIdentifier = process.BaseContext?.CurrentUserPrincipal?.Identity?.Name; logger.Fatal(entry); } else { var entry = LogEntry.Trace(message: innerResult.GetFaultMessage(), payload: args); entry.ProcessName = process.Name; entry.Action = process.Name; entry.Origin = ApplicationConfiguration.Instance?.ApplicationName ?? Environment.MachineName; entry.Payload = args?.SerializeJson(); entry.UserIdentifier = process.BaseContext?.CurrentUserPrincipal?.Identity?.Name; logger.Info(entry); } } return(innerResult); }
/// <summary> /// Send email on startup /// </summary> private static void NotifyOnStartup() { var config = BackgroundApplicationConfiguration.Instance.StartupNotificationConfiguration; var smtpClient = SystemBootstrapper.GetInstance <ISmtpClient>(); if (!smtpClient.IsNull() && !config.IsNull()) { var tos = config.Emails; var subject = config.Subject; var body = config.Body; if (tos.IsNullOrHasZeroElements()) { return; } if (subject.IsNullOrEmpty()) { return; } if (body.IsNullOrEmpty()) { return; } var from = ApplicationConfiguration.Instance.ApplicationEmail; var message = new MailMessage(); message.From = new MailAddress(from); message.Subject = subject; message.Body = body; message.IsBodyHtml = true; foreach (var to in tos) { message.To.Add(to); } var sendTask = smtpClient.SendMailAsync(message); Task.WaitAll(sendTask); } }
/// <summary> /// OWIN middleware registration extension /// </summary> /// <param name="app"></param> /// <param name="configurationCallback"></param> /// <returns></returns> public static IAppBuilder MapSignals(this IAppBuilder app, Action <FluentWebApplicationBootstrapConfiguration> configurationCallback) { var ass = AppDomain.CurrentDomain.GetAssemblies(); // get entry assembly StackTrace stackTrace = new StackTrace(); // TODO: workaround for tests var assembly = stackTrace.GetFrame(1).GetMethod().DeclaringType.Assembly; // configure web applicaiton var configuration = new FluentWebApplicationBootstrapConfiguration(); configurationCallback(configuration); configuration.ScanAssemblies.Add(assembly); configuration.Bootstrap(configuration.ScanAssemblies.ToArray()); // register midleware for handling session app.Use(async(IOwinContext context, Func <Task> next) => { HttpContextBase httpContext = context.Get <HttpContextBase>(typeof(HttpContextBase).FullName); httpContext.SetSessionStateBehavior(SessionStateBehavior.Required); await next.Invoke(); }); // handle session app.UseStageMarker(PipelineStage.MapHandler); var mediator = SystemBootstrapper.GetInstance <WebMediator>(); // mediator middleware return(app.Use(async(IOwinContext context, Func <Task> next) => { if (mediator.Dispatch() != MiddlewareResult.StopExecutionAndStopMiddlewarePipe) { await next.Invoke(); } })); }
/// <summary> /// Authorization callback /// </summary> /// <param name="feature"></param> /// <returns></returns> internal bool Authorize(string feature) { var permissionManager = SystemBootstrapper.GetInstance <IPermissionManager>(); return(permissionManager.HasPermission(feature, Roles.Cast <Enum>().ToArray())); }
/// <summary> /// Register all aspects into dependency resolver /// </summary> /// <returns></returns> public IServiceContainer Bootstrap(params Assembly[] scanAssemblies) { // Proc config validation ApplicationConfiguration config = null; try { config = ApplicationConfiguration.Instance; } catch { } finally { if (config.IsNull()) { throw new Exception("Signals.Core.Configuration.ApplicationConfiguration is not provided. Please use a configuration provider to provide configuration values!"); } } if (DependencyResolver.IsNull() || DependencyResolver().IsNull()) { throw new Exception("Dependency resolver not configured"); } var resolver = DependencyResolver(); if (!Logging.IsNull() && !Logging().IsNull()) { resolver.Register(typeof(ILogger), Logging()); } if (!Auditing.IsNull() && !Auditing().IsNull()) { resolver.Register(typeof(IAuditProvider), Auditing()); } if (!Cache.IsNull() && !Cache().IsNull()) { resolver.Register(typeof(ICache), Cache()); } if (!Localization.IsNull() && !Localization().IsNull()) { resolver.Register(typeof(ILocalizationProvider), Localization()); } if (!Storage.IsNull() && !Storage().IsNull()) { resolver.Register(typeof(IStorageProvider), Storage()); } if (!MessageChannel.IsNull() && !MessageChannel().IsNull()) { resolver.Register(typeof(IMessageChannel), MessageChannel()); } if (!AuthenticationManager.IsNull() && !AuthenticationManager().IsNull()) { resolver.Register(typeof(IAuthenticationManager), AuthenticationManager()); } if (!AuthorizationManager.IsNull() && !AuthorizationManager().IsNull()) { resolver.Register(typeof(IAuthorizationManager), AuthorizationManager()); } if (!TaskRegistry.IsNull() && !TaskRegistry().IsNull()) { resolver.Register(typeof(ITaskRegistry), TaskRegistry()); } if (!PermissionProvider.IsNull() && !PermissionProvider().IsNull()) { resolver.Register(typeof(IPermissionProvider), PermissionProvider()); } if (!Benchmarker.IsNull() && !Benchmarker().IsNull()) { resolver.Register(typeof(IBenchmarker), Benchmarker()); } if (!PermissionManager.IsNull() && !PermissionManager().IsNull()) { resolver.Register(typeof(IPermissionManager), PermissionManager()); } resolver.Register <CriticalErrorCallbackManager>(); resolver.Register <IProcessFactory, ProcessFactory>(); resolver.Register <IProcessExecutor, ProcessExecutor>(); resolver.Register <IBusinessProcessContext, BusinessProcessContext>(); resolver.Register <IApiProcessContext, ApiProcessContext>(); resolver.Register <IDistributedProcessContext, DistributedProcessContext>(); resolver.Register <IFileExportProcessContext, FileExportProcessContext>(); resolver.Register <IFileImportProcessContext, FileImportProcessContext>(); resolver.Register <IRecurringProcessContext, RecurringProcessContext>(); resolver.Register <Mediator>(); RegisterProcesses(config, resolver, scanAssemblies); RegisterErrorHendling(config, resolver); RegisterJsonSerializerSettings(config, resolver); RegisterSmtp(config, resolver); RegisterSyncLogProvider(config, resolver); var services = SystemBootstrapper.Init(resolver, scanAssemblies); return(services); }
/// <summary> /// Executed when test class is initialized /// </summary> public BaseProcessesTest() { string environment = null; FileConfigurationProvider ProviderForFile(string name) => new FileConfigurationProvider { File = name, Path = environment.IsNullOrEmpty() ? Path.Combine(AppContext.BaseDirectory, $"configs") : Path.Combine(AppContext.BaseDirectory, $"configs", environment), ReloadOnAccess = false }; EnvironmentConfiguration.UseProvider(ProviderForFile("environment.config.json")); environment = EnvironmentConfiguration.Instance.Environment; ApplicationConfiguration.UseProvider(ProviderForFile("application.config.json")); DomainConfiguration.UseProvider(ProviderForFile("domain.config.json")); TestBootstrapConfiguraiton config = new TestBootstrapConfiguraiton { RegistrationService = new RegistrationService(), CacheConfiguration = new InMemoryCacheConfiguration { DataProvider = new InMemoryDataProvider(), ExpirationPolicy = CacheExpirationPolicy.Sliding, ExpirationTime = TimeSpan.FromMinutes(1) }, LoggerConfiguration = new DatabaseLoggingConfiguration { Database = DomainConfiguration.Instance.DatabaseConfiguration.ActiveConfiguration.Database, Host = DomainConfiguration.Instance.DatabaseConfiguration.ActiveConfiguration.IpAddress, Username = DomainConfiguration.Instance.DatabaseConfiguration.ActiveConfiguration.Uid, Password = DomainConfiguration.Instance.DatabaseConfiguration.ActiveConfiguration.Pwd, DataProvider = DataProvider.SqlClient, TableName = "LogEntity" }, LocalizationConfiguration = new JsonDataProviderConfiguration { DirectoryPath = Path.Combine(AppContext.BaseDirectory, "system.resources"), FileExtension = "app", LocalizationSources = new List <LocalizationSource> { new LocalizationSource { Name = "Mail messages", SourcePath = "mailmessages" }, new LocalizationSource { Name = "Validation rules", SourcePath = "validationrules" }, new LocalizationSource { Name = "Pages", SourcePath = "pages" }, new LocalizationSource { Name = "Processes", SourcePath = "processes" } } }, StrategyBuilder = new StrategyBuilder().SetAutoHandling(false) }; config.JsonSerializerSettings = new Newtonsoft.Json.JsonSerializerSettings(); config.JsonSerializerSettings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb); var assemblies = Directory.GetFiles(AppContext.BaseDirectory, "*.dll").Select(file => Assembly.LoadFrom(file)).ToArray(); config.Bootstrap(assemblies); SystemBootstrapper.Bootstrap(this); }
/// <summary> /// Get api document generated from all api processes /// </summary> /// <returns></returns> private OpenApiDocument GenerateDocs() { var headers = SystemBootstrapper.GetInstance <List <ResponseHeaderAttribute> >(); var processRepo = SystemBootstrapper.GetInstance <ProcessRepository>(); var allApiProcesses = processRepo.OfType <IApiProcess>(); var document = new OpenApiDocument { Info = new OpenApiInfo { Version = ApplicationConfiguration.Instance.ApplicationVersion, Title = ApplicationConfiguration.Instance.ApplicationName, }, Servers = new List <OpenApiServer> { new OpenApiServer { Url = $"{WebApplicationConfiguration.Instance.WebUrl.TrimEnd('/')}/api/" } }, Paths = new OpenApiPaths(), Components = new OpenApiComponents() }; if (allApiProcesses.Any()) { var assemblyNamespace = allApiProcesses.First().Assembly.FullName.Split(',')[0]; foreach (var type in allApiProcesses) { var instance = SystemBootstrapper.GetInstance(type) as IBaseProcess <VoidResult>; var attribute = type.GetCustomAttributes(typeof(SignalsApiAttribute), false).Cast <SignalsApiAttribute>().SingleOrDefault(); var headerAttributes = type .GetCustomAttributes(typeof(ResponseHeaderAttribute), false) .Cast <ResponseHeaderAttribute>() .Concat(headers) .DistinctBy(x => x.Headers.Keys) .ToList(); var contentType = EnumExtensions.GetDescription(SerializationFormat.Json); var httpMethod = SignalsApiMethod.ANY; if (!attribute.IsNull()) { if (attribute.ExposeApiDocs == false) { continue; } contentType = EnumExtensions.GetDescription(attribute.ResponseType); httpMethod = attribute.HttpMethod; } var pathItem = new OpenApiPathItem(); var operationItem = new OpenApiOperation(); var path = type.FullName.Replace(assemblyNamespace, "").Replace('.', '/'); var processGenerics = type.BaseType.GetGenericArguments(); var headersDictionary = new Dictionary <string, OpenApiHeader>(); foreach (var header in headerAttributes) { foreach (var headerValue in header.Headers) { headersDictionary.Add(headerValue.Key, new OpenApiHeader { Schema = new OpenApiSchema { Type = "string" }, Example = new OpenApiString(headerValue.Value) }); } } operationItem.Tags = new List <OpenApiTag> { new OpenApiTag { Name = type.Namespace.Split('.').Last() } }; operationItem.Summary = instance.Description.IsNullOrEmpty() ? instance.Name : instance.Description; operationItem.Description = instance.Name; operationItem.OperationId = type.Name; // Determine the request based on the process type Type request = null; Type response; var processType = type.BaseType.Name; switch (processType) { case "ProxyApiProcess`5": request = processGenerics[3]; break; case "ProxyApiProcess`4": request = processGenerics[1]; break; case "ProxyApiProcess`3": break; case "AutoApiProcess`3": request = processGenerics[2]; break; case "AutoApiProcess`2": request = processGenerics[1]; break; case "AutoApiProcess`1": break; default: request = processGenerics.Length > 1 ? processGenerics.First() : null; break; } // Determine the response based on the process type if (processType.StartsWith("ProxyApiProcess") || processType.StartsWith("AutoApiProcess")) { var underlyingProcessType = processGenerics.First(); var underlyingProcessGenerics = underlyingProcessType.BaseType.GetGenericArguments(); response = underlyingProcessGenerics.Any() ? underlyingProcessGenerics.Last() : null; } else { response = processGenerics.Last(); } // Determine the payload response if (response != null) { if (response.Name.StartsWith("MethodResult") || response.Name.StartsWith("ListResult")) { response = response.GetGenericArguments().First(); } else if (response.Name.StartsWith("VoidResult")) { response = null; } } var enumTypes = new List <Type>(); var requestSchema = Deserialize(request, ref enumTypes); var responseSchema = Deserialize(response, ref enumTypes); var requestPath = string.Empty; if (request != null) { requestPath = $"{request.Namespace.Replace($"{assemblyNamespace}.", string.Empty)}.{request.Name}"; } var responsePath = string.Empty; if (response != null) { responsePath = $"{response.Namespace.Replace($"{assemblyNamespace}.", string.Empty)}.{response.Name}"; } if (!requestSchema.IsNullOrHasZeroElements()) { if (httpMethod == SignalsApiMethod.POST) { operationItem.RequestBody = new OpenApiRequestBody { Content = new Dictionary <string, OpenApiMediaType> { { contentType, new OpenApiMediaType { Schema = new OpenApiSchema { Reference = request != null ? new OpenApiReference { Id = $"definitions/{requestPath}", Type = ReferenceType.Schema, ExternalResource = "" } : null, Properties = requestSchema } } } } }; } else { foreach (var pair in requestSchema) { if (pair.Value.Properties.Any()) { operationItem.Parameters.Add(new OpenApiParameter { In = ParameterLocation.Query, Name = pair.Key, Reference = request != null ? new OpenApiReference { Id = $"definitions/{requestPath}", Type = ReferenceType.Schema, ExternalResource = "" } : null, Schema = pair.Value }); if (!document.Components.Schemas.ContainsKey(requestPath)) { document.Components.Schemas.Add($"{requestPath}", new OpenApiSchema { Properties = pair.Value.Properties }); } } else { operationItem.Parameters.Add(new OpenApiParameter { In = ParameterLocation.Query, Name = pair.Key, Schema = pair.Value }); } } } } operationItem.Responses = new OpenApiResponses { ["default"] = new OpenApiResponse { Content = new Dictionary <string, OpenApiMediaType> { { contentType, new OpenApiMediaType { Schema = new OpenApiSchema { Reference = new OpenApiReference { Id = $"definitions/{responsePath}", Type = ReferenceType.Schema, ExternalResource = "" }, Properties = responseSchema } } } }, Headers = headersDictionary } }; if (request != null) { if (!document.Components.Schemas.ContainsKey(requestPath)) { document.Components.Schemas.Add(requestPath, new OpenApiSchema { Properties = requestSchema }); } } if (response != null) { if (!document.Components.Schemas.ContainsKey(responsePath)) { document.Components.Schemas.Add(responsePath, new OpenApiSchema { Properties = responseSchema }); } } foreach (var enumType in enumTypes) { if (!document.Components.Schemas.ContainsKey(enumType.Name)) { var enums = Enum.GetNames(enumType).Select(x => new OpenApiString(x)).Cast <IOpenApiAny>().ToList(); document.Components.Schemas.Add(enumType.Name, new OpenApiSchema { Enum = enums, Type = "string" }); } } pathItem.Operations = new Dictionary <OperationType, OpenApiOperation>(); foreach (var method in Map(httpMethod)) { pathItem.Operations.Add(method, operationItem); } document.Paths.Add(path, pathItem); } } return(document); Dictionary <string, OpenApiSchema> Deserialize(Type type, ref List <Type> enumTypes) { if (type == null) { return(null); } var result = new Dictionary <string, OpenApiSchema>(); // Set schema props of the parent property var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public); Stack <OpenApiSchemaNode> toProcess = new Stack <OpenApiSchemaNode>(properties.Select(x => new OpenApiSchemaNode { Property = x })); Stack <OpenApiSchema> parentSchemas = new Stack <OpenApiSchema>(); var MAX_DEPTH = 5; // build the object hierarchy while (toProcess.Count > 0) { var propertyNode = toProcess.Pop(); var schema = GetOpenApiSchema(propertyNode.Property, ref enumTypes); var parentSchema = parentSchemas.Count == 0 ? null : parentSchemas.Pop(); if (propertyNode.Depth == MAX_DEPTH) { continue; } if (parentSchema != null) { if (parentSchema.Type == "array") { parentSchema.Items = parentSchema.Items ?? new OpenApiSchema(); parentSchema.Items.Properties.Add(schema.Title, schema); } else { parentSchema.Properties.Add(schema.Title, schema); } } else { result.Add(propertyNode.Property.Name, schema); } // process the complex types if (!propertyNode.Property.PropertyType.IsPrimitive && !propertyNode.Property.PropertyType.IsValueType && !typeof(IEnumerable).IsAssignableFrom(propertyNode.Property.PropertyType) && typeof(string) != propertyNode.Property.PropertyType) { properties = propertyNode.Property.PropertyType.GetProperties(BindingFlags.Instance | BindingFlags.Public); foreach (var propertyInfo in properties) { toProcess.Push(new OpenApiSchemaNode { Property = propertyInfo, Depth = propertyNode.Depth + 1 }); parentSchemas.Push(schema); } } else if (typeof(IDictionary).IsAssignableFrom(propertyNode.Property.PropertyType)) { var argument = propertyNode.Property.PropertyType.GetGenericArguments().LastOrDefault(); var value = GetDefaultValue(argument); var obj = new { @string = value }; properties = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public); foreach (var propertyInfo in properties) { toProcess.Push(new OpenApiSchemaNode { Property = propertyInfo, Depth = propertyNode.Depth + 1 }); parentSchemas.Push(schema); } } else if (typeof(IEnumerable).IsAssignableFrom(propertyNode.Property.PropertyType) && typeof(string) != propertyNode.Property.PropertyType) { properties = propertyNode.Property.PropertyType .GetGenericArguments() .FirstOrDefault()? .GetProperties(BindingFlags.Instance | BindingFlags.Public) ?? new PropertyInfo[0]; foreach (var propertyInfo in properties) { toProcess.Push(new OpenApiSchemaNode { Property = propertyInfo, Depth = propertyNode.Depth + 1 }); parentSchemas.Push(schema); } } } return(result); } object GetDefaultValue(Type t) { if (t.IsValueType && Nullable.GetUnderlyingType(t) == null) { return(Activator.CreateInstance(t)); } else { return(null); } } OpenApiSchema GetOpenApiSchema(PropertyInfo property, ref List <Type> enumTypes) { var schema = new OpenApiSchema { Title = property.Name }; // set the property name if (typeof(IEnumerable).IsAssignableFrom(property.PropertyType) && typeof(string) != property.PropertyType) { schema.Type = "array"; return(schema); } else if (property.PropertyType.IsEnum) { var enums = Enum.GetNames(property.PropertyType).Select(x => new OpenApiString(x)).Cast <IOpenApiAny>().ToList(); schema.Enum = enums; schema.Type = property.PropertyType.Name; schema.Format = "int32"; schema.Example = enums.FirstOrDefault(); schema.Reference = new OpenApiReference { Id = $"definitions/{property.PropertyType.Name}", Type = ReferenceType.Schema, ExternalResource = "" }; enumTypes.Add(property.PropertyType); return(schema); } switch (Type.GetTypeCode(property.PropertyType)) { case TypeCode.Boolean: { schema.Type = "boolean"; break; } case TypeCode.Byte: { schema.Type = "string"; schema.Format = "byte"; break; } case TypeCode.Char: { schema.Type = "string"; break; } case TypeCode.DateTime: { schema.Type = "string"; schema.Format = "date-time"; break; } case TypeCode.Decimal: { schema.Type = "number"; schema.Format = "double"; break; } case TypeCode.Double: { schema.Type = "number"; schema.Format = "double"; break; } case TypeCode.Int16: { schema.Type = "integer"; schema.Format = "int32"; break; } case TypeCode.Int32: { schema.Type = "integer"; schema.Format = "int32"; break; } case TypeCode.Int64: { schema.Type = "integer"; schema.Format = "int64"; break; } case TypeCode.SByte: { schema.Type = "string"; schema.Format = "byte"; break; } case TypeCode.Single: { schema.Type = "number"; schema.Format = "float"; break; } case TypeCode.String: { schema.Type = "string"; break; } case TypeCode.UInt16: { schema.Type = "integer"; schema.Format = "int32"; break; } case TypeCode.UInt32: { schema.Type = "integer"; schema.Format = "int32"; break; } case TypeCode.UInt64: { schema.Type = "integer"; schema.Format = "int64"; break; } } return(schema); } // map http method to open api method List <OperationType> Map(SignalsApiMethod method) { if (method == SignalsApiMethod.ANY) { return new List <OperationType> { OperationType.Get, OperationType.Post } } ; else if (method == SignalsApiMethod.DELETE) { return new List <OperationType> { OperationType.Delete, } } ; else if (method == SignalsApiMethod.GET) { return new List <OperationType> { OperationType.Get, } } ; else if (method == SignalsApiMethod.OPTIONS) { return new List <OperationType> { OperationType.Options, } } ; else if (method == SignalsApiMethod.PATCH) { return new List <OperationType> { OperationType.Patch, } } ; else if (method == SignalsApiMethod.POST) { return new List <OperationType> { OperationType.Post, } } ; else if (method == SignalsApiMethod.PUT) { return new List <OperationType> { OperationType.Put, } } ; return(new List <OperationType>()); } }
public static HtmlString Translate(this IHtmlHelper helper, string key) { var translation = SystemBootstrapper.GetInstance <ILocalizationProvider>()?.Get(key)?.Value; return(new HtmlString(translation ?? "Localization provider not initialized")); }
/// <summary> /// Execute handler /// </summary> /// <typeparam name="TResult"></typeparam> /// <param name="process"></param> /// <param name="processType"></param> /// <param name="args"></param> /// <returns></returns> public TResult Execute <TResult>(IBaseProcess <TResult> process, Type processType, params object[] args) where TResult : VoidResult, new() { try { return(Next.Execute(process, processType, args)); } catch (Exception ex) { var criticalAttributes = processType.GetCustomAttributes(typeof(CriticalAttribute), true).Cast <CriticalAttribute>().ToList(); if (criticalAttributes.Any()) { var manager = SystemBootstrapper.GetInstance <CriticalErrorCallbackManager>(); manager?.InvokeError(process, processType, args, ex); } var happeningDate = DateTime.UtcNow; if (ApplicationConfiguration.Instance?.CriticalConfiguration != null) { string InterpolateException(string originalString) { return(originalString .Replace("[#Date#]", happeningDate.ToString(CultureInfo.InvariantCulture)) .Replace("[#Process#]", processType.Name) .Replace("[#Message#]", ex.Message) .Replace("[#StackTrace#]", ex.StackTrace) .Replace("[#Data#]", args?.SerializeJson())); } var client = SystemBootstrapper.GetInstance <ISmtpClient>(); if (!client.IsNull()) { foreach (var attribute in criticalAttributes) { var emails = attribute.NotificaitonEmails?.Split(',')?.Select(x => x.Trim())?.ToList(); if (!emails.IsNullOrHasZeroElements()) { var from = ApplicationConfiguration.Instance.ApplicationEmail; var to = emails; var subject = InterpolateException(ApplicationConfiguration.Instance.CriticalConfiguration.Subject); var body = InterpolateException(ApplicationConfiguration.Instance.CriticalConfiguration.Body); var data = $@"Date: {happeningDate.ToString(CultureInfo.InvariantCulture)}{Environment.NewLine} Process: {processType.Name}{Environment.NewLine} Message: {ex.Message}{Environment.NewLine} StackTrace: {ex.StackTrace}{Environment.NewLine} Data: {args?.SerializeJson()}{Environment.NewLine}"; Attachment attachment = Attachment.CreateAttachmentFromString(data, "critical_info.txt"); var message = new MailMessage(); message.From = new MailAddress(from); message.Subject = subject; message.Body = body; message.IsBodyHtml = true; foreach (var email in emails) { message.To.Add(email); } message.Attachments.Add(attachment); client.Send(message); } } } } throw; } }