protected bool CheckValidity(IProcessingContext processingContext, KraftModule module, LoadedNodeSet loadedNodeSet) { if (processingContext.InputModel.LoaderType == ELoaderType.None) { Utilities.ExtensionMethods.KraftResult(_HttpContext, HttpStatusCode.NotFound, $"You have to specify a loader type."); return(false); } if (module == null) { Utilities.ExtensionMethods.KraftResult(_HttpContext, HttpStatusCode.NotFound, $"Requested module: {processingContext.InputModel.Module} doesn't exist or not loaded."); return(false); } if (loadedNodeSet == null) { Utilities.ExtensionMethods.KraftResult(_HttpContext, HttpStatusCode.NotFound, $"Requested nodeset: {processingContext.InputModel.NodeSet} doesn't exist or not loaded."); return(false); } if (loadedNodeSet.StartNode == null)//Handle errors better and show when a node is addressed but missing. { string error = $"Node: {processingContext.InputModel.Nodepath} from module: {processingContext.InputModel.Module}, nodeset: {processingContext.InputModel.NodeSet} is missing!"; KraftLogger.LogError(error); Utilities.ExtensionMethods.KraftResult(_HttpContext, HttpStatusCode.InternalServerError, error); return(false); } //If authentication is required but the user is not logged in redirect to authentication if (loadedNodeSet.StartNode.RequireAuthentication && !processingContext.InputModel.SecurityModel.IsAuthenticated) { Utilities.ExtensionMethods.KraftResult(_HttpContext, HttpStatusCode.Unauthorized, null); return(false); } return(true); }
public static void RestartApplication(IHostApplicationLifetime applicationLifetime, RestartReason restartReason, Action <bool> restart = null) { try { if (applicationLifetime != null) { if (restartReason != null) { KraftLogger.LogDebug($"Method: RestartApplication: Stopping application Reason: {restartReason.Reason} additional info {restartReason.Description}"); } applicationLifetime.StopApplication(); if (!applicationLifetime.ApplicationStopping.IsCancellationRequested) { Task.Delay(10 * 1000, applicationLifetime.ApplicationStopping); } restart?.Invoke(true); } else { KraftLogger.LogDebug("Method: RestartApplication: applicationLifetime is null."); } } catch (Exception exception) { KraftLogger.LogError(exception, "Method: RestartApplication(IApplicationLifetime applicationLifetime)"); } }
private static void HandleError(IApplicationBuilder builder) { if (Exceptions.Any(p => p.Value.Any())) { builder.Run( async context => { context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; context.Response.ContentType = "text/html"; IExceptionHandlerFeature error = context.Features.Get <IExceptionHandlerFeature>(); if (error != null) { await context.Response.WriteAsync($"<h1>Error: {error.Error.Message}</h1>").ConfigureAwait(false); } StringBuilder errorDetails = new StringBuilder(); foreach (KeyValuePair <string, List <Exception> > ex in Exceptions) { foreach (Exception val in ex.Value) { errorDetails.Append($"<h2>Error on {ex.Key}: {val.Message}</h2>"); errorDetails.Append($"<h3>Further details: {val.StackTrace}</h3>"); } } await context.Response.WriteAsync(errorDetails.ToString()).ConfigureAwait(false); KraftLogger.LogError(errorDetails.ToString()); }); return; } }
public static void KraftResult(HttpContext httpContext, HttpStatusCode statusCode, string error = null) { httpContext.Response.StatusCode = (int)statusCode; switch (statusCode) { case HttpStatusCode.InternalServerError: { if (!string.IsNullOrEmpty(error)) { KraftLogger.LogCritical(error); } httpContext.Request.Headers.Clear(); break; } case HttpStatusCode.Unauthorized: { //HttpRequest request = httpContext.Request; httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized; //string redirectUrl = string.Concat(request.Scheme, "://", request.Host.ToUriComponent(), request.PathBase.ToUriComponent(), request.Path.ToUriComponent(), request.QueryString.ToUriComponent()); //httpContext.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties() { RedirectUri = redirectUrl }); break; } default: { if (!string.IsNullOrEmpty(error)) { KraftLogger.LogError(error); } httpContext.Request.Headers.Clear(); break; } } }
public void Execute( LoadedNodeSet loaderContextDefinition, IProcessingContext processingContext, IPluginAccessor <IDataLoaderPlugin> dataLoaderAccessor, IPluginAccessor <INodePlugin> pluginAccessor) { _CollectiveCall = true; //Check for null values GenericUtilities.CheckNullOrEmpty(loaderContextDefinition, true); GenericUtilities.CheckNullOrEmpty(processingContext, true); GenericUtilities.CheckNullOrEmpty(_TransactionScope.PluginServiceManager, true); try { if (processingContext.InputModel.LoaderType.HasFlag(ELoaderType.DataLoader)) { ExecuteNodeData(loaderContextDefinition, processingContext, dataLoaderAccessor, pluginAccessor); } if (processingContext.InputModel.LoaderType.HasFlag(ELoaderType.ViewLoader)) { ExecuteNodeView(loaderContextDefinition, processingContext); } //if (processingContext.InputModel.LoaderType.HasFlag(ELoaderType.LookupLoader)) //{ // if (loaderContextDefinition.StartNode != null && loaderContextDefinition.StartNode.HasLookup()) // { // using (KraftProfiler.Current.Step("Execution time loading lookups: ")) // { // foreach (Lookup lookup in loaderContextDefinition.StartNode.Lookups) // { // ISystemPlugin systemPlugin = Utilities.GetPlugin<ISystemPlugin>(lookup.SystemPluginName, _TransactionScope.DependencyInjectionContainer, _KraftModuleConfigurationSettings, ELoaderType.LookupLoader); // GenericUtilities.CheckNullOrEmpty(systemPlugin, true); // IPluginsSynchronizeContextScoped synchronizeContextScoped = await _TransactionScope.GetSynchronizeContextScopedAsync(lookup.SystemPluginName, ELoaderType.LookupLoader, _KraftModuleConfigurationSettings, systemPlugin); // GenericUtilities.CheckNullOrEmpty(synchronizeContextScoped, true); // await systemPlugin.ExecuteAsync(loaderContextDefinition, processingContext, _TransactionScope.PluginServiceManager, synchronizeContextScoped, lookup); // } // } // } //} _TransactionScope.CommitTransactions(); } catch (Exception ex) { processingContext.ReturnModel.Status.IsSuccessful = false; processingContext.ReturnModel.Status.StatusResults.Add(new StatusResult { StatusResultType = EStatusResult.StatusResultError, Message = ex.Message }); _TransactionScope.RollbackTransactions(); KraftLogger.LogError(ex.Message, ex); } finally { _CollectiveCall = false; } }
private static Assembly AppDomain_OnAssemblyResolve(object sender, ResolveEventArgs args) { // Ignore missing resources if (args.Name.Contains(".resources")) { return(null); } // check for assemblies already loaded string[] nameParts = args.Name.Split(','); Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => { string[] parts = a.FullName.Split(','); return(parts[0].Equals(nameParts[0], StringComparison.InvariantCultureIgnoreCase)); } ); if (assembly != null) { return(assembly); } // Try to load by filename - split out the filename of the full assembly name // and append the base path of the original assembly (ie. look in the same dir) string fileName = nameParts[0] + ".dll".ToLower(); bool found = false; foreach (string dir in _KraftGlobalConfigurationSettings.GeneralSettings.ModulesRootFolders) { string asmFullName = Path.Combine(dir, "_PluginsReferences", fileName); try { Assembly loadedAssembly = Assembly.LoadFile(asmFullName); if (loadedAssembly != null) { found = true; return(loadedAssembly); } } catch { //do nothing continue; } finally { if (!found) { KraftLogger.LogError($"Method: CurrentDomain_AssemblyResolve: The file {asmFullName} requested by {args.RequestingAssembly.FullName} was not found!"); } } } return(null); }
private void FileWatcher_Changed(object sender, FileSystemEventArgs e) { FileSystemWatcher fileWatcher = sender as FileSystemWatcher; fileWatcher.EnableRaisingEvents = false; KraftLogger.LogError("FileWatcher_Changed PhysicalPath: " + PhysicalPath); KraftLogger.LogError("FileWatcher_Changed VirtualPath: " + VirtualPath); fileWatcher.Changed -= new FileSystemEventHandler(FileWatcher_Changed); fileWatcher.Dispose(); _Parent?.RemoveFromCache(); }
protected virtual void ExecuteQuery <Context>(Context execContext) where Context : class, IDataLoaderContext { bool trace = execContext.CurrentNode.Trace; string qry = GetQuery(execContext); if (qry != null) { try { var runner = Compiler.Compile(qry); if (runner.ErrorText != null) { KraftLogger.LogError($"{execContext.LocationInfo(PLUGIN_INTERNAL_NAME)}\n{runner.ErrorText}"); throw new Exception(runner.ErrorText); } using (var host = new ActionQueryHost <Context>(execContext) { { "HostInfo", HostInfo } }) { if (trace) { host.Trace = true; } try { var result = runner.ExecuteScalar(host, ActionQueryHost <Context> .HardLimit(execContext)); } catch { if (trace) { var traceInfo = host.GetTraceInfo(); if (traceInfo != null) { KraftLogger.LogError($"{execContext.LocationInfo(PLUGIN_INTERNAL_NAME)}\n"); KraftLogger.LogError(traceInfo.ToString()); } } throw; } } } catch (Exception ex) { KraftLogger.LogError(ActionQueryTrace.ExceptionToString(ex)); throw; } } }
public void ExecuteNodeView( LoadedNodeSet loaderContextDefinition, IProcessingContext processingContext) { if (!_CollectiveCall) { //Check for null values GenericUtilities.CheckNullOrEmpty(loaderContextDefinition, true); GenericUtilities.CheckNullOrEmpty(processingContext, true); GenericUtilities.CheckNullOrEmpty(_TransactionScope.PluginServiceManager, true); } try { using (KraftProfiler.Current.Step("Execution time loading views: ")) { if (!string.IsNullOrEmpty(processingContext.InputModel.BindingKey)) { View view = loaderContextDefinition.StartNode.Views.Find(v => v.BindingKey.Equals(processingContext.InputModel.BindingKey, StringComparison.OrdinalIgnoreCase)); ExecuteNodeViewPrivate(loaderContextDefinition, processingContext, view); } else { foreach (View view in loaderContextDefinition.StartNode.Views) { ExecuteNodeViewPrivate(loaderContextDefinition, processingContext, view); } } } if (!_CollectiveCall) { _TransactionScope.CommitTransactions(); } } catch (Exception ex) { processingContext.ReturnModel.Status.IsSuccessful = false; processingContext.ReturnModel.Status.StatusResults.Add(new StatusResult { StatusResultType = EStatusResult.StatusResultError, Message = ex.Message }); if (!_CollectiveCall) { _TransactionScope.RollbackTransactions(); } KraftLogger.LogError(ex.Message, ex); } }
public void ExecuteNodeData( LoadedNodeSet loaderContextDefinition, IProcessingContext processingContext, IPluginAccessor <IDataLoaderPlugin> dataLoaderAccessor, IPluginAccessor <INodePlugin> pluginAccessor) { if (!_CollectiveCall) { //Check for null values GenericUtilities.CheckNullOrEmpty(loaderContextDefinition, true); GenericUtilities.CheckNullOrEmpty(processingContext, true); GenericUtilities.CheckNullOrEmpty(_TransactionScope.PluginServiceManager, true); } try { if (processingContext.InputModel.LoaderType.HasFlag(ELoaderType.DataLoader)) { using (KraftProfiler.Current.Step("Execution time loading data: ")) { if (loaderContextDefinition.StartNode != null && loaderContextDefinition.StartNode.HasValidDataSection(processingContext.InputModel.IsWriteOperation)) { IDataIteratorPlugin dataIteratorPlugin = Utilities.GetPlugin <IDataIteratorPlugin>(_KraftModuleConfigurationSettings.NodeSetSettings.SourceLoaderMapping.NodesDataIterator.NodesDataIteratorConf.Name, _TransactionScope.DependencyInjectionContainer, _KraftModuleConfigurationSettings, ELoaderType.DataLoader, true); GenericUtilities.CheckNullOrEmpty(dataIteratorPlugin, true); IProcessingContext r = dataIteratorPlugin.ExecuteAsync(loaderContextDefinition, processingContext, _TransactionScope.PluginServiceManager, dataLoaderAccessor, pluginAccessor).Result; } } } if (!_CollectiveCall) { _TransactionScope.CommitTransactions(); } } catch (Exception ex) { processingContext.ReturnModel.Status.IsSuccessful = false; processingContext.ReturnModel.Status.StatusResults.Add(new StatusResult { StatusResultType = EStatusResult.StatusResultError, Message = ex.Message }); if (!_CollectiveCall) { _TransactionScope.RollbackTransactions(); } KraftLogger.LogError(ex.Message, ex); } }
protected override List <Dictionary <string, object> > Read(IDataLoaderReadContext execContext) { string baseUrl = execContext.DataLoaderContextScoped.CustomSettings["BaseUrl"]; ParameterResolverValue endpoint = execContext.Evaluate("endpoint"); ParameterResolverValue method = execContext.Evaluate("method"); var result = new List <Dictionary <string, object> >(); if (!(endpoint.Value is string)) { KraftLogger.LogError("HttpServiceImp endpoint parameter value must be string"); throw new Exception("endpoint value must be string"); } string url = baseUrl + endpoint.Value; var obj = this.GetHttpContent(url); result.Add(new Dictionary <string, object>() { { "key", obj } }); return(result); }
private async Task <string> GetHttpContent(string url) { KraftLogger.LogTrace(url); try { using (var http = new HttpClient()) { var httpResponse = await http.GetAsync(url); var httpContent = await httpResponse.Content.ReadAsStringAsync(); if (httpResponse.StatusCode.ToString().StartsWith("5") || httpResponse.StatusCode.ToString().StartsWith("4")) { KraftLogger.LogWarning("Recieved status code:" + httpResponse.StatusCode, httpResponse); } return(httpContent); } } catch (Exception ex) { KraftLogger.LogError(ex, "Method: GetHttpContent"); throw; } }
protected override void ExecuteWrite(IDataLoaderWriteContext execContext) { bool trace = execContext.CurrentNode.Trace; string qry = GetQuery(execContext); if (qry != null) { try { var runner = Compiler.Compile(qry); if (runner.ErrorText != null) { KraftLogger.LogError($"{execContext.LocationInfo(PLUGIN_INTERNAL_NAME)}\n{runner.ErrorText}"); throw new Exception(runner.ErrorText); } using (var host = new ActionQueryHost <IDataLoaderWriteContext>(execContext) { { nameof(IsPostedFile), IsPostedFile }, { nameof(PostedFileSize), PostedFileSize }, { nameof(PostedFileName), PostedFileName }, { nameof(PostedFileType), PostedFileType }, { nameof(CombinePaths), CombinePaths }, { nameof(DeleteFile), DeleteFile }, { nameof(SaveFile), SaveFile }, { nameof(PrependFileName), PrependFileName }, { nameof(CreateDirectory), CreateDirectory }, { nameof(SaveFileToSpread), SaveFileToSpread }, { nameof(PostedFile), this.PostedFile }, { nameof(FileResponse), FileResponse }, { nameof(FileExists), FileExists } }) { host.AddLibrary(new BasicImageLib <IDataLoaderWriteContext>()); if (trace) { host.Trace = true; } try { var result = runner.ExecuteScalar(host, ActionQueryHost <IDataLoaderWriteContext> .HardLimit(execContext)); } catch { if (trace) { var traceInfo = host.GetTraceInfo(); if (traceInfo != null) { KraftLogger.LogError($"{execContext.LocationInfo(PLUGIN_INTERNAL_NAME)}\n"); KraftLogger.LogError(traceInfo.ToString()); } KraftLogger.LogError($"{runner.DumpProgram()}\n"); } throw; } } } catch (Exception ex) { KraftLogger.LogError(ActionQueryTrace.ExceptionToString(ex)); throw; } } // Else nothing to do. }
public static IServiceProvider UseBindKraft(this IServiceCollection services, IConfiguration configuration) { try { services.AddDistributedMemoryCache(); services.UseBindKraftLogger(); // If using Kestrel: services.Configure <KestrelServerOptions>(options => { options.AllowSynchronousIO = true; }); // If using IIS: services.Configure <IISServerOptions>(options => { options.AllowSynchronousIO = true; }); _KraftGlobalConfigurationSettings = new KraftGlobalConfigurationSettings(); configuration.GetSection("KraftGlobalConfigurationSettings").Bind(_KraftGlobalConfigurationSettings); _Configuration = configuration; services.AddSingleton(_KraftGlobalConfigurationSettings); if (_KraftGlobalConfigurationSettings.GeneralSettings.RedirectToHttps) { services.Configure <ForwardedHeadersOptions>(options => { options.KnownNetworks.Clear(); //its loopback by default options.KnownProxies.Clear(); options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; }); services.AddHsts(options => { options.Preload = true; options.IncludeSubDomains = true; options.MaxAge = TimeSpan.FromDays(365); }); services.AddHttpsRedirection(options => { options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect; options.HttpsPort = 443; }); } if (_KraftGlobalConfigurationSettings.GeneralSettings.SignalRSettings.UseSignalR) { services.AddSignalR(hubOptions => { hubOptions.KeepAliveInterval = TimeSpan.FromDays(1); hubOptions.EnableDetailedErrors = true; hubOptions.HandshakeTimeout = TimeSpan.FromSeconds(30); hubOptions.ClientTimeoutInterval = TimeSpan.FromSeconds(60); }); } //GRACE DEPENDENCY INJECTION CONTAINER DependencyInjectionContainer dependencyInjectionContainer = new DependencyInjectionContainer(); services.AddSingleton(dependencyInjectionContainer); services.AddRouting(options => options.LowercaseUrls = true); services.AddResponseCaching(); services.AddMemoryCache(); services.AddSession(options => { // Set a short timeout for easy testing. options.IdleTimeout = TimeSpan.FromMinutes(60); // You might want to only set the application cookies over a secure connection: options.Cookie.SecurePolicy = CookieSecurePolicy.Always; options.Cookie.SameSite = SameSiteMode.Strict; options.Cookie.HttpOnly = true; // Make the session cookie essential options.Cookie.IsEssential = true; }); ToolSettings tool = KraftToolsRouteBuilder.GetTool(_KraftGlobalConfigurationSettings, "profiler"); if (tool != null && tool.Enabled)//Profiler enabled enabled from configuration { services.UseBindKraftProfiler(tool.Url); } IServiceProvider serviceProvider = services.BuildServiceProvider(); IWebHostEnvironment env = serviceProvider.GetRequiredService <IWebHostEnvironment>(); ILoggerFactory loggerFactory = serviceProvider.GetRequiredService <ILoggerFactory>(); _Logger = loggerFactory.CreateLogger <KraftMiddleware>(); services.AddLogging(loggingBuilder => { loggingBuilder.ClearProviders(); if (env.IsDevelopment()) { loggingBuilder.SetMinimumLevel(LogLevel.Error); loggingBuilder.AddConsole(); loggingBuilder.AddDebug(); } }); //memory cache _MemoryCache = serviceProvider.GetRequiredService <IMemoryCache>(); /*if (_HostingEnvironment.IsDevelopment()) * { * config.CacheProfiles.Add("Default", new CacheProfile() { Location = ResponseCacheLocation.None, Duration = 0 }); * } * else * { * config.CacheProfiles.Add("Default", new CacheProfile() { Location = ResponseCacheLocation.Any, Duration = 60 }); * }*/ ICachingService cachingService = new MemoryCachingService(_MemoryCache); services.AddSingleton(cachingService); KraftModuleCollection kraftModuleCollection = new KraftModuleCollection(_KraftGlobalConfigurationSettings, dependencyInjectionContainer, _Logger); services.AddSingleton(kraftModuleCollection); #region Global Configuration Settings _KraftGlobalConfigurationSettings.GeneralSettings.ReplaceMacrosWithPaths(env.ContentRootPath, env.WebRootPath); #endregion //Global Configuration Settings //INodeSet service services.AddSingleton(typeof(INodeSetService), new NodeSetService(_KraftGlobalConfigurationSettings, cachingService)); ILogger logger = loggerFactory.CreateLogger(env.EnvironmentName); services.AddSingleton(typeof(ILogger), logger); services.AddSingleton(services); #region Authorization if (_KraftGlobalConfigurationSettings.GeneralSettings.AuthorizationSection.RequireAuthorization) { services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; }) .AddCookie(options => { options.LoginPath = new PathString("/account/signin"); }) .AddOpenIdConnect(options => { // Note: these settings must match the application details // inserted in the database at the server level. options.ClientId = _KraftGlobalConfigurationSettings.GeneralSettings.ClientId; options.ClientSecret = _KraftGlobalConfigurationSettings.GeneralSettings.ClientSecret; options.RequireHttpsMetadata = _KraftGlobalConfigurationSettings.GeneralSettings.RedirectToHttps; options.Authority = _KraftGlobalConfigurationSettings.GeneralSettings.Authority; options.GetClaimsFromUserInfoEndpoint = true; options.SaveTokens = true; // Use the authorization code flow. options.ResponseType = OpenIdConnectResponseType.Code; options.AuthenticationMethod = OpenIdConnectRedirectBehavior.RedirectGet; options.Scope.Add("email"); options.Scope.Add("roles"); options.Scope.Add("firstname"); options.Scope.Add("lastname"); options.Scope.Add("offline_access"); options.Events = new OpenIdConnectEvents { OnRedirectToIdentityProvider = context => { string returnUrl = context.HttpContext.Session.GetString("returnurl");//Has returnurl already in user's session if (string.IsNullOrEmpty(returnUrl)) { if (context.Request.Query.ContainsKey("returnurl"))//Is passed as parameter in the url { returnUrl = context.Request.Query["returnurl"]; } } if (!string.IsNullOrEmpty(returnUrl)) { context.ProtocolMessage.SetParameter("returnurl", returnUrl); } return(Task.CompletedTask); }, OnRemoteFailure = context => { KraftLogger.LogWarning("OnRemoteFailure in KraftMiddlewareExtensions", context.Failure); HttpRequest request = context.Request; foreach (var cookie in context.Request.Cookies) { if (!cookie.Key.Equals(CookieRequestCultureProvider.DefaultCookieName, StringComparison.OrdinalIgnoreCase)) { context.Response.Cookies.Delete(cookie.Key); } } string redirectUrl = string.Concat(request.Scheme, "://", request.Host.ToUriComponent(), request.PathBase.ToUriComponent()); context.Response.Redirect(redirectUrl); context.HandleResponse(); return(Task.CompletedTask); }, OnAuthenticationFailed = context => { KraftLogger.LogError("OnAuthenticationFailed in KraftMiddlewareExtensions", context.Exception); HttpRequest request = context.Request; context.Properties.RedirectUri = context.ProtocolMessage.RedirectUri?.Replace("http://", "https://"); return(Task.CompletedTask); }, OnTokenValidated = context => { if (context.ProtocolMessage.Parameters.ContainsKey("returnurl"))//This is coming from the authorization server { string returnurl = context.ProtocolMessage.Parameters["returnurl"]; context.Properties.RedirectUri = returnurl; if (!string.IsNullOrEmpty(returnurl)) { context.HttpContext.Session.SetString("returnurl", returnurl); } } else if (!string.IsNullOrEmpty(_KraftGlobalConfigurationSettings.GeneralSettings.AuthorizationSection.RedirectAfterLogin)) { context.Properties.RedirectUri = _KraftGlobalConfigurationSettings.GeneralSettings.AuthorizationSection.RedirectAfterLogin; } return(Task.CompletedTask); } }; options.SecurityTokenValidator = new JwtSecurityTokenHandler { // Disable the built-in JWT claims mapping feature. InboundClaimTypeMap = new Dictionary <string, string>() }; options.TokenValidationParameters.NameClaimType = "name"; options.TokenValidationParameters.RoleClaimType = "role"; }); } else { services.AddAuthorization(x => { x.DefaultPolicy = new AuthorizationPolicyBuilder() .RequireAssertion(_ => true) .Build(); }); } #endregion Authorization services.UseBundling(); //Dataprotection //This should supress The antiforgery token could not be decrypted error TODO check the logs DirectoryInfo dataProtection = new DirectoryInfo(Path.Combine(env.ContentRootPath, "DataProtection")); if (!dataProtection.Exists) { dataProtection.Create(); } services.AddDataProtection(opts => { opts.ApplicationDiscriminator = "corekraft"; }) .PersistKeysToFileSystem(dataProtection) .SetDefaultKeyLifetime(TimeSpan.FromDays(10)); //End Dataprotection services.Configure <HubOptions>(options => { options.MaximumReceiveMessageSize = null; }); //Signals services.AddHostedService <SignalService>(); //End Signals //RecordersStore which contians dictionary of the running instances services.AddSingleton <RecordersStoreImp>(); } catch (Exception ex) { KraftLogger.LogError("Method: ConfigureServices ", ex); KraftExceptionHandlerMiddleware.Exceptions[KraftExceptionHandlerMiddleware.EXCEPTIONSONCONFIGURESERVICES].Add(ex); } return(services.BuildServiceProvider()); }
internal DbConnection GetConnection() { if (_DbConnection == null) { //Create connection string moduleRoot = System.IO.Path.Combine(KraftGlobalConfigurationSettings.GeneralSettings.ModulesRootFolder(ProcessingContext.InputModel.Module), ProcessingContext.InputModel.Module); // Support for @moduleroot@ variable replacement for connection strings that refer to file(s) string connectionString = (CustomSettings != null && CustomSettings.ContainsKey("ConnectionString")) ? CustomSettings["ConnectionString"].Replace("@moduleroot@", moduleRoot) : null; if (string.IsNullOrEmpty(connectionString)) { throw new NullReferenceException("The Connection String must not be null or empty."); } // MatchCollection matches = _DynamicParameterRegEx.Matches(connectionString); connectionString = _DynamicParameterRegEx.Replace(connectionString, m => { string varname = m.Groups[1].Value; var val = LoaderContext.Evaluate(varname); if (val.ValueType == EResolverValueType.Invalid) { KraftLogger.LogError($"Expected parameter in connection string: {m.Groups[1].Value} was not resolved! Check that parameter's expression. It is recommended to not define it on node basis, but only in a nodeset root!"); // TODO: What shall we return on error? This is temporary decision - there should be something better or just excepton. return(m.Value); } if (!string.IsNullOrWhiteSpace(val.Value + "")) { return(val.Value.ToString()); } else { KraftLogger.LogError($"Expected parameter in connection string: {m.Groups[1].Value} was not found or cannot be resolved!"); return(m.Value); } }); /*if (matches.Count > 0) { * for (int i = 0; i < matches.Count; i++) { * * string parameter = matches[i].Groups["OnlyParameter"].ToString(); * * if (ProcessingContext.InputModel.Data.ContainsKey(parameter)) { * * connectionString = connectionString.Replace(matches[i].ToString(), ProcessingContext.InputModel.Data[parameter].ToString()); * } * else if (ProcessingContext.InputModel.Client.ContainsKey(parameter)) { * * connectionString = connectionString.Replace(matches[i].ToString(), ProcessingContext.InputModel.Client[parameter].ToString()); * } * else { * * KraftLogger.LogError($"Expected parameter in connection string: {matches[i]} was not found and the connection string remains invalid! Please consider the casing!"); * //connectionString = connectionString.Replace(matches[i].ToString(), string.Empty); * } * } * }*/ _DbConnection = KraftProfiler.Current.ProfiledDbConnection(new XConnection()); _DbConnection.ConnectionString = connectionString; } if (_DbConnection.State != ConnectionState.Open) { _DbConnection.Open(); } return(_DbConnection); }
/// <summary> /// Reads uploaded file in predefined directory, /// sets the response builder of the return model of the processing context to BinaryResponseBuilder. /// </summary> /// <param name="execContext">Execution context</param> /// <returns>null</returns> protected override List <Dictionary <string, object> > Read(IDataLoaderReadContext execContext) { ReadCustomSettings settings = new ReadCustomSettings(execContext, execContext.PluginServiceManager.GetService <KraftGlobalConfigurationSettings>(typeof(KraftGlobalConfigurationSettings))); string filePreviewName = "FILE_preview.svg"; string previewName = "preview"; string file = execContext.Evaluate("path").Value.ToString(); string configuredDir = settings.UploadFolder; string defaultDir = settings.DefaultFolder; if (File.Exists(Path.Combine(configuredDir, file))) { ParameterResolverValue preview = execContext.Evaluate(previewName); if (preview.Value != null) { string previewValue = preview.Value.ToString(); if (previewValue == "1") { string previewFileName = GeneratePreviewName(file); if (File.Exists(Path.Combine(configuredDir, previewFileName))) { file = previewFileName; } else { string extension = Path.GetExtension(file); if (!string.IsNullOrWhiteSpace(extension)) { previewFileName = extension.Replace(".", string.Empty).ToUpper() + "_preview.svg"; if (File.Exists(Path.Combine(defaultDir, previewFileName))) { file = previewFileName; configuredDir = defaultDir; } else { file = filePreviewName; configuredDir = defaultDir; } } else { file = filePreviewName; configuredDir = defaultDir; } } } } } else { if (File.Exists(Path.Combine(defaultDir, settings.FileNotFoundIcon))) { configuredDir = defaultDir; file = settings.FileNotFoundIcon; } else { KraftLogger.LogError($"FileUploadImp-Read: File with name {file} was not found."); } } file = Path.Combine(configuredDir, file); string contentType; new FileExtensionContentTypeProvider().TryGetContentType(file, out contentType); execContext.ProcessingContext.ReturnModel.BinaryData = new PostedFile(contentType, 0, "currentlyNotSet", file, path => { return(File.Open(path as string, FileMode.Open)); }, file); execContext.ProcessingContext.ReturnModel.ResponseBuilder = new BinaryResponseBuilder(new ProcessingContextCollection(new List <IProcessingContext> { execContext.ProcessingContext })); return(null); }
/// <summary> /// Unlike read write is called exactly once per each row and not called at all if the row's state does not require actual writing. /// </summary> /// <param name="execContext"></param> /// <param name="configuration"></param> /// <returns></returns> protected override object Write(IDataLoaderWriteContext execContext) { //IDataLoaderContext execContext, Configuration configuration) { string sqlQuery = null; try { Node node = execContext.CurrentNode; // Statement is already selected for the requested operation (While fetching the Configuration if (!string.IsNullOrWhiteSpace(Action(execContext)?.Query)) { // Check if it is valid if (!(execContext.OwnContextScoped is IADOTransactionScope scopedContext)) { throw new NullReferenceException("Scoped synchronization and transaction context is not available."); } // Settings should be passed to the scopedContext in the ExternalServiceImp DbConnection conn = scopedContext.Connection; DbTransaction trans = scopedContext.StartADOTransaction(); using (DbCommand cmd = conn.CreateCommand()) { cmd.Transaction = trans; cmd.Parameters.Clear(); sqlQuery = ProcessCommand(cmd, Action(execContext).Query, execContext); using (DbDataReader reader = cmd.ExecuteReader()) { do { while (reader.Read()) { for (int i = 0; i < reader.FieldCount; i++) { string fname = reader.GetName(i); if (fname == null) { continue; } fname = fname.ToLower().Trim(); // fname = fname.Trim(); // TODO: We have to rethink this - lowercasing seems more inconvenience than a viable protection against human mistakes. if (fname.Length == 0) { throw new Exception("Empty field name in a store context in nodedesfinition: " + node.NodeSet.Name); } object v = reader.GetValue(i); execContext.Row[fname] = (v is DBNull) ? null : v; } } // This is important, we have been doing this for a single result before, but it is better to assume more than one, so that // update of the data being written can be done more freely - using more than one select statement after writing. This is // probably rare, but having the opportunity is better than not having it. } while (reader.NextResult()); if (execContext.Operation != OPERATION_DELETE) { execContext.DataState.SetUnchanged(execContext.Row); } } } } } catch (Exception ex) { if (!string.IsNullOrEmpty(sqlQuery)) { KraftLogger.LogError($"Write(IDataLoaderWriteContext execContext) >> SQL: {Environment.NewLine}{sqlQuery}", ex, execContext); } throw; } return(null); // if this is not null it should add new results in the data // TODO: Consider if this is possible and useful (for some future version - not urgent). }
public static IApplicationBuilder UseBindKraft(this IApplicationBuilder app, IHostingEnvironment env) { //AntiforgeryService //app.Use(next => context => //{ // if (string.Equals(context.Request.Path.Value, "/", StringComparison.OrdinalIgnoreCase)) // { // AntiforgeryTokenSet tokens = app.ApplicationServices.GetService<IAntiforgery>().GetAndStoreTokens(context); // context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false }); // } // return next(context); //}); _KraftGlobalConfigurationSettings.EnvironmentSettings = new KraftEnvironmentSettings(env.ApplicationName, env.ContentRootPath, env.EnvironmentName, env.WebRootPath); try { ILoggerFactory loggerFactory = app.ApplicationServices.GetService <ILoggerFactory>(); DiagnosticListener diagnosticListener = app.ApplicationServices.GetService <DiagnosticListener>(); //First statement to register Error handling !!!Keep at the top!!! app.UseMiddleware <KraftExceptionHandlerMiddleware>(loggerFactory, new ExceptionHandlerOptions(), diagnosticListener); AppDomain.CurrentDomain.UnhandledException += AppDomain_OnUnhandledException; AppDomain.CurrentDomain.AssemblyResolve += AppDomain_OnAssemblyResolve; if (_KraftGlobalConfigurationSettings.GeneralSettings.RedirectToWww) { RewriteOptions rewrite = new RewriteOptions(); rewrite.AddRedirectToWwwPermanent(); app.UseRewriter(rewrite); } if (_KraftGlobalConfigurationSettings.GeneralSettings.RedirectToHttps) { app.UseForwardedHeaders(); app.UseHsts(); app.UseHttpsRedirection(); } ExtensionMethods.Init(app, _Logger); app.UseBindKraftLogger(env, loggerFactory, ERRORURLSEGMENT); app.UseBindKraftProfiler(env, loggerFactory, _MemoryCache); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } _Builder = app; BundleCollection bundleCollection = app.UseBundling(env, loggerFactory.CreateLogger("Bundling"), _KraftGlobalConfigurationSettings.GeneralSettings.KraftUrlCssJsSegment, _KraftGlobalConfigurationSettings.GeneralSettings.EnableOptimization); bundleCollection.EnableInstrumentations = env.IsDevelopment(); //Logging enabled #region Initial module registration foreach (string dir in _KraftGlobalConfigurationSettings.GeneralSettings.ModulesRootFolders) { if (!Directory.Exists(dir)) { throw new Exception($"No \"{dir}\" directory found! The CoreKraft initialization cannot continue."); } } string kraftUrlSegment = _KraftGlobalConfigurationSettings.GeneralSettings.KraftUrlSegment; try { KraftModuleCollection modulesCollection = app.ApplicationServices.GetService <KraftModuleCollection>(); Dictionary <string, string> moduleKey2Path = new Dictionary <string, string>(); IApplicationLifetime applicationLifetime = app.ApplicationServices.GetRequiredService <IApplicationLifetime>(); lock (_SyncRoot) { foreach (string dir in _KraftGlobalConfigurationSettings.GeneralSettings.ModulesRootFolders) { string[] moduleDirectories = Directory.GetDirectories(dir); foreach (string subdirectory in moduleDirectories) { DirectoryInfo moduleDirectory = new DirectoryInfo(subdirectory); if (moduleDirectory.Name != null && moduleDirectory.Name.Equals("_PluginsReferences", StringComparison.InvariantCultureIgnoreCase)) { continue; } ICachingService cachingService = app.ApplicationServices.GetService <ICachingService>(); KraftModule kraftModule = modulesCollection.GetModule(moduleDirectory.Name); if (kraftModule != null) { continue; } kraftModule = modulesCollection.RegisterModule(dir, moduleDirectory.Name, cachingService); if (kraftModule == null || !kraftModule.IsInitialized) { _Logger.LogInformation($"Module not created for directory \"{moduleDirectory.Name}\" because of missing configuration files."); continue; } KraftStaticFiles.RegisterStaticFiles(app, moduleDirectory.FullName, kraftUrlSegment, _KraftGlobalConfigurationSettings.GeneralSettings.KraftUrlResourceSegment, _KraftGlobalConfigurationSettings.GeneralSettings.KraftUrlModuleImages); KraftStaticFiles.RegisterStaticFiles(app, moduleDirectory.FullName, kraftUrlSegment, _KraftGlobalConfigurationSettings.GeneralSettings.KraftUrlResourceSegment, _KraftGlobalConfigurationSettings.GeneralSettings.KraftUrlModulePublic); moduleKey2Path.Add(kraftModule.Key.ToLower(), dir); //The application will restart when some files changed in the modules directory and subdirectories but only in RELEASE //Check if module is initialized Robert if (kraftModule.IsInitialized && !env.IsDevelopment()) { string moduleFullPath = Path.Combine(dir, kraftModule.Key); AttachModulesWatcher(moduleFullPath, false, applicationLifetime); string path2Data = Path.Combine(moduleFullPath, "Data"); if (!HasWritePermissionOnDir(new DirectoryInfo(path2Data), true)) { throw new SecurityException($"Write access to folder {path2Data} is required!"); } path2Data = Path.Combine(moduleFullPath, "Images"); if (!HasWritePermissionOnDir(new DirectoryInfo(path2Data), true)) { throw new SecurityException($"Write access to folder {path2Data} is required!"); } AttachModulesWatcher(Path.Combine(moduleFullPath, "Css"), true, applicationLifetime); AttachModulesWatcher(Path.Combine(moduleFullPath, "Documentation"), true, applicationLifetime); AttachModulesWatcher(Path.Combine(moduleFullPath, "Localization"), true, applicationLifetime); AttachModulesWatcher(Path.Combine(moduleFullPath, "NodeSets"), true, applicationLifetime); AttachModulesWatcher(Path.Combine(moduleFullPath, "Scripts"), true, applicationLifetime); AttachModulesWatcher(Path.Combine(moduleFullPath, "Templates"), true, applicationLifetime); AttachModulesWatcher(Path.Combine(moduleFullPath, "Views"), true, applicationLifetime); } } } //try to construct all modules modulesCollection.ResolveModuleDependencies(); _KraftGlobalConfigurationSettings.GeneralSettings.ModuleKey2Path = moduleKey2Path; } if (!env.IsDevelopment()) { _Configuration.GetReloadToken().RegisterChangeCallback(_ => { RestartReason restartReason = new RestartReason(); restartReason.Reason = "Configuration Changed"; restartReason.Description = $"'appsettings.Production.json' has been altered"; AppDomain.CurrentDomain.UnhandledException -= AppDomain_OnUnhandledException; AppDomain.CurrentDomain.AssemblyResolve -= AppDomain_OnAssemblyResolve; RestartApplication(applicationLifetime, restartReason); }, null); } } catch (Exception boom) { KraftLogger.LogError(boom); throw new Exception($"CoreKrafts module construction failed! {boom.Message}"); } #endregion Initial module registration //Configure the CoreKraft routing RouteHandler kraftRoutesHandler = new RouteHandler(KraftMiddleware.ExecutionDelegate(app, _KraftGlobalConfigurationSettings)); app.UseRouter(KraftRouteBuilder.MakeRouter(app, kraftRoutesHandler, kraftUrlSegment)); app.UseSession(); if (_KraftGlobalConfigurationSettings.GeneralSettings.AuthorizationSection.RequireAuthorization) { app.UseAuthentication(); } //KraftKeepAlive.RegisterKeepAliveAsync(builder); //Configure eventually SignalR try { if (_KraftGlobalConfigurationSettings.GeneralSettings.SignalRSettings.UseSignalR) { app.UseSignalR(routes => { MethodInfo mapHub = typeof(HubRouteBuilder).GetMethod("MapHub", new[] { typeof(PathString) }); MethodInfo generic = mapHub.MakeGenericMethod(Type.GetType(_KraftGlobalConfigurationSettings.GeneralSettings.SignalRSettings.HubImplementationAsString)); generic.Invoke(routes, new object[] { new PathString(_KraftGlobalConfigurationSettings.GeneralSettings.SignalRSettings.HubRoute) }); }); } } catch (Exception e) { KraftLogger.LogError("Register signalR middleware. Exception: " + e); } //Signals SignalStartup signalStartup = new SignalStartup(app.ApplicationServices, _KraftGlobalConfigurationSettings); signalStartup.ExecuteSignalsOnStartup(); //End Signals } catch (Exception ex) { KraftLogger.LogError("Method: UseBindKraft ", ex); KraftExceptionHandlerMiddleware.Exceptions[KraftExceptionHandlerMiddleware.EXCEPTIONSONCONFIGURE].Add(ex); } //This is the last statement KraftExceptionHandlerMiddleware.HandleErrorAction(app); return(app); }
/* Considerations: * We have to read the configuration in a single turn and consume it from the internal configuration container * in order to avoid direct hard coded dependency on the system configuration structure - most notably dependency on its * structure and interpreatation. * Solution: * We have a nested class in which the configuration values used by this loader are collected (sometimes with some preprocessing) * Lifecycle: * The configuration (part of it at least) has a lifecycle equal to the node execution which is shorter than the life of the dataloader (at least potentially), * so the configuration has to be reread on each node executio and thus is not persisted in the loader's instance, but passed to the main overridable methods. * */ //protected class Configuration { // public string Statement { get; set; } //} /// <summary> /// /// </summary> /// <param name="execContext"></param> /// <returns></returns> //protected virtual Configuration ReadConfiguration(IDataLoaderContext execContext) { // var cfg = new Configuration(); // if (execContext.Action == ACTION_READ) { // cfg.Statement = execContext.CurrentNode.Read.Select.HasStatement?execContext.CurrentNode.Read.Select.Query:null; // } else if (execContext.Action == ACTION_WRITE) { // switch (execContext.Operation) { // case OPERATION_INSERT: // if (execContext.CurrentNode.Write.Insert.HasStatement) { // cfg.Statement = execContext.CurrentNode.Write.Insert.Query; // } // break; // case OPERATION_UPDATE: // if (execContext.CurrentNode.Write.Update.HasStatement) { // cfg.Statement = execContext.CurrentNode.Write.Update.Query; // } // break; // case OPERATION_DELETE: // if (execContext.CurrentNode.Write.Delete.HasStatement) { // cfg.Statement = execContext.CurrentNode.Write.Delete.Query; // } // break; // } // } // return cfg; /////////////////////////////// //} #endregion //public async Task<object> ExecuteAsync(IDataLoaderContext execContext) { // // The procedure is different enough to deserve splitting by read/write // Configuration cfg = ReadConfiguration(execContext); // object result; // if (execContext.Action == ACTION_WRITE) { // result = ExecuteWrite(execContext, cfg); // } else if (execContext.Action == ACTION_READ) { // result = ExecuteRead(execContext, cfg); // } else { // // unknown action // throw new Exception("Unknown action (only read/write) are supported"); // } // return await Task.FromResult(result); //} protected override List <Dictionary <string, object> > Read(IDataLoaderReadContext execContext) { // TODO: What to return if there is no statement: // I think we should have two policies - empty object which enables children extraction if logically possible and // null wich stops the processing here. List <Dictionary <string, object> > results = new List <Dictionary <string, object> >(); string sqlQuery = null; try { Node node = execContext.CurrentNode; if (!string.IsNullOrWhiteSpace(Action(execContext).Query)) { // Scope context for the same loader // Check it is valid if (!(execContext.OwnContextScoped is IADOTransactionScope scopedContext)) { throw new NullReferenceException("Scoped synchronization and transaction context is not available."); } // Configuration settings Should be set to the scoped context during its creation/obtainment - see ExternalServiceImp // No tranaction in read mode - lets not forget that closing the transaction also closes the connection - so the ;ifecycle control will do this using the transaction based notation // from ITransactionScope DbConnection conn = scopedContext.Connection; using (DbCommand cmd = conn.CreateCommand()) { cmd.Transaction = scopedContext.CurrentTransaction; // if we decide to open transaction in future this will guarantee we only have to open it and will take effect throughout the code. cmd.Parameters.Clear(); // This will set the resulting command text if everything is Ok. // The processing will make replacements in the SQL and bind parameters by requesting them from the resolver expressions configured on this node. // TODO: Some try...catching is necessary. sqlQuery = ProcessCommand(cmd, Action(execContext).Query, execContext); using (DbDataReader reader = cmd.ExecuteReader()) { do { if (reader.HasRows) { // Read a result (many may be contained) row by row while (reader.Read()) { Dictionary <string, object> currentResult = new Dictionary <string, object>(reader.FieldCount); for (int i = 0; i < reader.FieldCount; i++) { string fldname = reader.GetName(i); if (fldname == null) { continue; } // TODO: May be configure that or at least create a compile time definition fldname = fldname.ToLower().Trim(); // TODO: lowercase //fldname = fldname.Trim(); if (fldname.Length == 0) { throw new Exception($"Empty name when reading the output of a query. The field index is {i}. The query is: {cmd.CommandText}"); } if (currentResult.ContainsKey(fldname)) { throw new Exception($"Duplicated field name in the output of a query. The field is:{fldname}, the query is: {cmd.CommandText}"); } object v = reader.GetValue(i); currentResult.Add(fldname, (v is DBNull) ? null : v); } // Mark the records unchanged, because they are just picked up from the data store (rdbms in this case). execContext.DataState.SetUnchanged(currentResult); results.Add(currentResult); if (!node.IsList) { break; } } } } while (reader.NextResult()); } } } } catch (Exception ex) { if (!string.IsNullOrEmpty(sqlQuery)) { KraftLogger.LogError($"Read(IDataLoaderReadContext execContext) >> SQL: {Environment.NewLine}{sqlQuery}", ex, execContext); } throw; } return(results); // TODO: Decide what behavior we want with empty statements. I for one prefer null result, effectively stopping the operation. }
public static IServiceProvider UseBindKraft(this IServiceCollection services, IConfiguration configuration) { try { services.AddDistributedMemoryCache(); services.UseBindKraftLogger(); _KraftGlobalConfigurationSettings = new KraftGlobalConfigurationSettings(); configuration.GetSection("KraftGlobalConfigurationSettings").Bind(_KraftGlobalConfigurationSettings); _Configuration = configuration; services.AddSingleton(_KraftGlobalConfigurationSettings); if (_KraftGlobalConfigurationSettings.GeneralSettings.RedirectToHttps) { services.Configure <ForwardedHeadersOptions>(options => { options.KnownNetworks.Clear(); //its loopback by default options.KnownProxies.Clear(); options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; }); services.AddHsts(options => { options.Preload = true; options.IncludeSubDomains = true; options.MaxAge = TimeSpan.FromDays(365); }); services.AddHttpsRedirection(options => { options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect; options.HttpsPort = 443; }); } if (_KraftGlobalConfigurationSettings.GeneralSettings.SignalRSettings.UseSignalR) { services.AddSignalR(hubOptions => { hubOptions.KeepAliveInterval = TimeSpan.FromDays(1); hubOptions.EnableDetailedErrors = true; }); } //GRACE DEPENDENCY INJECTION CONTAINER DependencyInjectionContainer dependencyInjectionContainer = new DependencyInjectionContainer(); services.AddSingleton(dependencyInjectionContainer); services.AddRouting(options => options.LowercaseUrls = true); services.AddResponseCaching(); services.AddMemoryCache(); services.AddSession(); services.UseBindKraftProfiler(); IServiceProvider serviceProvider = services.BuildServiceProvider(); IHostingEnvironment env = serviceProvider.GetRequiredService <IHostingEnvironment>(); ILoggerFactory loggerFactory = serviceProvider.GetRequiredService <ILoggerFactory>(); _Logger = loggerFactory.CreateLogger <KraftMiddleware>(); services.AddLogging(loggingBuilder => { loggingBuilder.ClearProviders(); if (env.IsDevelopment()) { loggingBuilder.SetMinimumLevel(LogLevel.Error); loggingBuilder.AddConsole(); loggingBuilder.AddDebug(); } }); //memory cache _MemoryCache = serviceProvider.GetRequiredService <IMemoryCache>(); /*if (_HostingEnvironment.IsDevelopment()) * { * config.CacheProfiles.Add("Default", new CacheProfile() { Location = ResponseCacheLocation.None, Duration = 0 }); * } * else * { * config.CacheProfiles.Add("Default", new CacheProfile() { Location = ResponseCacheLocation.Any, Duration = 60 }); * }*/ ICachingService cachingService = new MemoryCachingService(_MemoryCache); services.AddSingleton(cachingService); KraftModuleCollection kraftModuleCollection = new KraftModuleCollection(_KraftGlobalConfigurationSettings, dependencyInjectionContainer, _Logger); services.AddSingleton(kraftModuleCollection); #region Global Configuration Settings _KraftGlobalConfigurationSettings.GeneralSettings.ReplaceMacrosWithPaths(env.ContentRootPath, env.WebRootPath); #endregion //Global Configuration Settings //INodeSet service services.AddSingleton(typeof(INodeSetService), new NodeSetService(_KraftGlobalConfigurationSettings, cachingService)); ILogger logger = loggerFactory.CreateLogger(env.EnvironmentName); services.AddSingleton(typeof(ILogger), logger); services.AddSingleton(services); #region Authorization if (_KraftGlobalConfigurationSettings.GeneralSettings.AuthorizationSection.RequireAuthorization) { services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; }) .AddCookie(options => { options.LoginPath = new PathString("/account/signin"); }) .AddOpenIdConnect(options => { // Note: these settings must match the application details // inserted in the database at the server level. options.ClientId = _KraftGlobalConfigurationSettings.GeneralSettings.ClientId; options.ClientSecret = _KraftGlobalConfigurationSettings.GeneralSettings.ClientSecret; options.RequireHttpsMetadata = _KraftGlobalConfigurationSettings.GeneralSettings.RedirectToHttps; options.Authority = _KraftGlobalConfigurationSettings.GeneralSettings.Authority; options.GetClaimsFromUserInfoEndpoint = true; options.SaveTokens = true; // Use the authorization code flow. options.ResponseType = OpenIdConnectResponseType.Code; options.AuthenticationMethod = OpenIdConnectRedirectBehavior.RedirectGet; options.Scope.Add("email"); options.Scope.Add("roles"); options.Scope.Add("firstname"); options.Scope.Add("lastname"); options.Scope.Add("offline_access"); options.Events = new OpenIdConnectEvents { OnRedirectToIdentityProvider = context => { if (context.Request.Query.ContainsKey("cr")) { context.ProtocolMessage.SetParameter("cr", context.Request.Query["cr"]); } return(Task.CompletedTask); }, OnRemoteFailure = context => { KraftLogger.LogError(context.Failure); HttpRequest request = context.Request; string redirectUrl = string.Concat(request.Scheme, "://", request.Host.ToUriComponent(), request.PathBase.ToUriComponent()); context.Response.Redirect(redirectUrl); // + "/" + ERRORURLSEGMENT + "?message=" + UrlEncoder.Default.Encode(context.Failure.Message)); context.HandleResponse(); return(Task.CompletedTask); }, OnAuthenticationFailed = context => { HttpRequest request = context.Request; context.ProtocolMessage.RedirectUri = context.ProtocolMessage.RedirectUri.Replace("http://", "https://"); context.HandleResponse(); return(Task.CompletedTask); } }; options.SecurityTokenValidator = new JwtSecurityTokenHandler { // Disable the built-in JWT claims mapping feature. InboundClaimTypeMap = new Dictionary <string, string>() }; options.TokenValidationParameters.NameClaimType = "name"; options.TokenValidationParameters.RoleClaimType = "role"; }); } else { services.AddAuthorization(x => { x.DefaultPolicy = new AuthorizationPolicyBuilder() .RequireAssertion(_ => true) .Build(); }); } #endregion Authorization services.UseBundling(); //services.AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo(Path.Combine(_KraftGlobalConfigurationSettings.GeneralSettings.ModulesRootFolder, "BindKraft", "Data"))); //Signals services.AddHostedService <SignalService>(); //End Signals } catch (Exception ex) { KraftLogger.LogError("Method: ConfigureServices ", ex); KraftExceptionHandlerMiddleware.Exceptions[KraftExceptionHandlerMiddleware.EXCEPTIONSONCONFIGURESERVICES].Add(ex); } return(services.BuildServiceProvider()); }
public static IApplicationBuilder UseBindKraft(this IApplicationBuilder app, IWebHostEnvironment env, Action <bool> restart = null) { //AntiforgeryService //app.Use(next => context => //{ // if (string.Equals(context.Request.Path.Value, "/", StringComparison.OrdinalIgnoreCase)) // { // AntiforgeryTokenSet tokens = app.ApplicationServices.GetService<IAntiforgery>().GetAndStoreTokens(context); // context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false }); // } // return next(context); //}); _KraftGlobalConfigurationSettings.EnvironmentSettings = new KraftEnvironmentSettings(env.ApplicationName, env.ContentRootPath, env.EnvironmentName, env.WebRootPath); try { ILoggerFactory loggerFactory = app.ApplicationServices.GetService <ILoggerFactory>(); DiagnosticListener diagnosticListener = app.ApplicationServices.GetService <DiagnosticListener>(); //First statement to register Error handling !!!Keep at the top!!! app.UseMiddleware <KraftExceptionHandlerMiddleware>(loggerFactory, new ExceptionHandlerOptions(), diagnosticListener); AppDomain.CurrentDomain.UnhandledException += AppDomain_OnUnhandledException; AppDomain.CurrentDomain.AssemblyResolve += AppDomain_OnAssemblyResolve; if (_KraftGlobalConfigurationSettings.GeneralSettings.RedirectToHttps) { app.UseForwardedHeaders(); app.UseHsts(); app.UseHttpsRedirection(); } if (_KraftGlobalConfigurationSettings.GeneralSettings.RedirectToWww) { RewriteOptions rewrite = new RewriteOptions(); rewrite.AddRedirectToWwwPermanent(); app.UseRewriter(rewrite); } app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "wwwroot")), ServeUnknownFileTypes = true, RequestPath = new PathString(string.Empty), }); ExtensionMethods.Init(app, _Logger); ToolSettings tool = KraftToolsRouteBuilder.GetTool(_KraftGlobalConfigurationSettings, "errors"); string segment = null; if (tool != null && tool.Enabled)//Errors enabled from configuration { segment = tool.Url; } app.UseBindKraftLogger(env, loggerFactory, segment); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } string rootVirtualPath = "/modules"; BundleCollection bundleCollection = app.UseBundling(env, _KraftGlobalConfigurationSettings.GeneralSettings.ModulesRootFolders, rootVirtualPath, loggerFactory.CreateLogger("Bundling"), _KraftGlobalConfigurationSettings.GeneralSettings.KraftUrlCssJsSegment, _KraftGlobalConfigurationSettings.GeneralSettings.EnableOptimization); bundleCollection.EnableInstrumentations = env.IsDevelopment(); //Logging enabled #region Initial module registration foreach (string dir in _KraftGlobalConfigurationSettings.GeneralSettings.ModulesRootFolders) { if (!Directory.Exists(dir)) { throw new Exception($"No \"{dir}\" directory found in the setting ModulesRootFolders! The CoreKraft initialization cannot continue."); } } string kraftUrlSegment = _KraftGlobalConfigurationSettings.GeneralSettings.KraftUrlSegment; try { KraftModuleCollection modulesCollection = app.ApplicationServices.GetService <KraftModuleCollection>(); IHostApplicationLifetime applicationLifetime = app.ApplicationServices.GetRequiredService <IHostApplicationLifetime>(); lock (_SyncRoot) { KraftModulesConstruction kraftModulesConstruction = new KraftModulesConstruction(); Dictionary <string, IDependable <KraftDependableModule> > kraftDependableModules = kraftModulesConstruction.Init(_KraftGlobalConfigurationSettings.GeneralSettings.DefaultStartModule, _KraftGlobalConfigurationSettings.GeneralSettings.ModulesRootFolders); ICachingService cachingService = app.ApplicationServices.GetService <ICachingService>(); Dictionary <string, string> moduleKey2Path = new Dictionary <string, string>(); foreach (KeyValuePair <string, IDependable <KraftDependableModule> > depModule in kraftDependableModules) { KraftDependableModule kraftDependable = (depModule.Value as KraftDependableModule); KraftModule kraftModule = modulesCollection.RegisterModule(kraftDependable.KraftModuleRootPath, depModule.Value.Key, kraftDependable, cachingService); KraftStaticFiles.RegisterStaticFiles(app, kraftModule.ModulePath, kraftUrlSegment, _KraftGlobalConfigurationSettings.GeneralSettings.KraftUrlResourceSegment, _KraftGlobalConfigurationSettings.GeneralSettings.KraftUrlModuleImages); KraftStaticFiles.RegisterStaticFiles(app, kraftModule.ModulePath, kraftUrlSegment, _KraftGlobalConfigurationSettings.GeneralSettings.KraftUrlResourceSegment, _KraftGlobalConfigurationSettings.GeneralSettings.KraftUrlModulePublic); moduleKey2Path.Add(kraftModule.Key, kraftDependable.KraftModuleRootPath); string moduleFullPath = Path.Combine(kraftDependable.KraftModuleRootPath, kraftModule.Key); string path2Data = Path.Combine(moduleFullPath, "Data"); if (!HasWritePermissionOnDir(new DirectoryInfo(path2Data), true)) { throw new SecurityException($"Write access to folder {path2Data} is required!"); } path2Data = Path.Combine(moduleFullPath, "Images"); if (!HasWritePermissionOnDir(new DirectoryInfo(path2Data), true)) { throw new SecurityException($"Write access to folder {path2Data} is required!"); } foreach (string validSubFolder in _ValidSubFoldersForWatching) { AttachModulesWatcher(Path.Combine(moduleFullPath, validSubFolder), true, applicationLifetime, restart); } } _KraftGlobalConfigurationSettings.GeneralSettings.ModuleKey2Path = moduleKey2Path; } #region Watching appsettings, PassThroughJsConfig, nlogConfig //appsettings.{Production} configuration watch _Configuration.GetReloadToken().RegisterChangeCallback(_ => { string environment = "Production"; if (env.IsDevelopment()) { environment = "Development"; } RestartReason restartReason = new RestartReason { Reason = "appsettings-Configuration Changed", Description = $"'appsettings.{environment}.json' has been altered" }; AppDomain.CurrentDomain.UnhandledException -= AppDomain_OnUnhandledException; AppDomain.CurrentDomain.AssemblyResolve -= AppDomain_OnAssemblyResolve; RestartApplication(applicationLifetime, restartReason, restart); }, null); //PassThroughJsConfig configuration watch IChangeToken changeTokenPassThroughJsConfig = _KraftGlobalConfigurationSettings.GeneralSettings.BindKraftConfigurationGetReloadToken(env); if (changeTokenPassThroughJsConfig != null) { changeTokenPassThroughJsConfig.RegisterChangeCallback(_ => { RestartReason restartReason = new RestartReason { Reason = "PassThroughJsConfig Changed", Description = $"'{_KraftGlobalConfigurationSettings.GeneralSettings.PassThroughJsConfig}' has been altered" }; AppDomain.CurrentDomain.UnhandledException -= AppDomain_OnUnhandledException; AppDomain.CurrentDomain.AssemblyResolve -= AppDomain_OnAssemblyResolve; RestartApplication(applicationLifetime, restartReason, restart); }, null); } FileInfo nlogConfig = new FileInfo(Path.Combine(env.ContentRootPath, "nlog.config")); if (nlogConfig.Exists) { IChangeToken changeTokenNlogConfig = env.ContentRootFileProvider.Watch(nlogConfig.Name); if (changeTokenNlogConfig != null) { changeTokenNlogConfig.RegisterChangeCallback(_ => { RestartReason restartReason = new RestartReason { Reason = "Nlog.config Changed", Description = $"'Nlog.config' has been altered" }; AppDomain.CurrentDomain.UnhandledException -= AppDomain_OnUnhandledException; AppDomain.CurrentDomain.AssemblyResolve -= AppDomain_OnAssemblyResolve; RestartApplication(applicationLifetime, restartReason, restart); }, null); } } #endregion End: Watching appsettings, PassThroughJsConfig, nlogConfig } catch (Exception boom) { KraftLogger.LogError(boom); throw new Exception($"CoreKrafts module construction failed! {boom.Message}"); } #endregion Initial module registration //Configure the CoreKraft routing RouteHandler kraftRoutesHandler = new RouteHandler(KraftMiddleware.ExecutionDelegate(app, _KraftGlobalConfigurationSettings)); app.UseRouter(KraftRouteBuilder.MakeRouter(app, kraftRoutesHandler, kraftUrlSegment)); #region Tools routing KraftToolsRouteBuilder.MakeRouters(app, _KraftGlobalConfigurationSettings); #endregion Tools routing DirectCallService.Instance.Call = KraftMiddleware.ExecutionDelegateDirect(app, _KraftGlobalConfigurationSettings); app.UseSession(); if (_KraftGlobalConfigurationSettings.GeneralSettings.AuthorizationSection.RequireAuthorization) { app.UseAuthentication(); } //KraftKeepAlive.RegisterKeepAliveAsync(builder); //Configure eventually SignalR try { if (_KraftGlobalConfigurationSettings.GeneralSettings.SignalRSettings.UseSignalR) { app.UseRouting(); app.UseEndpoints(endpoints => { MethodInfo mapHub = typeof(HubEndpointRouteBuilderExtensions).GetMethod( "MapHub", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(IEndpointRouteBuilder), typeof(string), typeof(Action <HttpConnectionDispatcherOptions>) }, null); MethodInfo generic = mapHub.MakeGenericMethod(Type.GetType(_KraftGlobalConfigurationSettings.GeneralSettings.SignalRSettings.HubImplementationAsString, true)); generic.Invoke(null, new object[] { endpoints, new string(_KraftGlobalConfigurationSettings.GeneralSettings.SignalRSettings.HubRoute), (Action <HttpConnectionDispatcherOptions>)(x => { x.ApplicationMaxBufferSize = 3200000; x.WebSockets.CloseTimeout = TimeSpan.FromSeconds(30); x.LongPolling.PollTimeout = TimeSpan.FromSeconds(180); }) }); }); } } catch (Exception e) { KraftLogger.LogError("Register signalR middleware. Exception: " + e); } //Signals SignalStartup signalStartup = new SignalStartup(app.ApplicationServices, _KraftGlobalConfigurationSettings); signalStartup.ExecuteSignalsOnStartup(); //End Signals } catch (Exception ex) { KraftLogger.LogError("Method: UseBindKraft ", ex); KraftExceptionHandlerMiddleware.Exceptions[KraftExceptionHandlerMiddleware.EXCEPTIONSONCONFIGURE].Add(ex); } //This is the last statement KraftExceptionHandlerMiddleware.HandleErrorAction(app); return(app); }