1
0
mirror of https://git.teknik.io/Teknikode/Teknik.git synced 2023-08-02 14:16:22 +02:00

Fixed migration issues and cleaned up startup

This commit is contained in:
Uncled1023 2021-06-30 21:54:59 -07:00
parent 3a6d4df991
commit 852f17c2ac
11 changed files with 49 additions and 493 deletions

View File

@ -18,12 +18,13 @@ using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Diagnostics;
using Teknik.Data; using Teknik.Data;
using Teknik.Logging; using Teknik.Logging;
using Teknik.WebCommon;
namespace Teknik.Areas.Error.Controllers namespace Teknik.Areas.Error.Controllers
{ {
[Authorize] [Authorize]
[Area("Error")] [Area("Error")]
public class ErrorController : DefaultController public class ErrorController : DefaultController, IErrorController
{ {
public ErrorController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { } public ErrorController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
@ -31,6 +32,16 @@ namespace Teknik.Areas.Error.Controllers
[TrackPageView] [TrackPageView]
public IActionResult HttpError(int statusCode) public IActionResult HttpError(int statusCode)
{ {
return HttpError(statusCode, null);
}
[AllowAnonymous]
[TrackPageView]
public IActionResult HttpError(int statusCode, Exception ex)
{
if (ex != null)
return Http500(ex);
switch (statusCode) switch (statusCode)
{ {
case 401: case 401:
@ -39,6 +50,8 @@ namespace Teknik.Areas.Error.Controllers
return Http403(); return Http403();
case 404: case 404:
return Http404(); return Http404();
case 500:
return Http500(ex);
default: default:
return HttpGeneral(statusCode); return HttpGeneral(statusCode);
} }

View File

@ -1,128 +0,0 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Teknik.Configuration;
namespace Teknik.Middleware
{
public class BlacklistMiddleware
{
private readonly RequestDelegate _next;
private readonly IMemoryCache _cache;
public BlacklistMiddleware(RequestDelegate next, IMemoryCache cache)
{
_next = next;
_cache = cache;
}
public async Task Invoke(HttpContext context, Config config)
{
// Beggining of Request
bool blocked = false;
string blockReason = string.Empty;
#region Detect Blacklisted IPs
if (!blocked)
{
string IPAddr = context.Request.HttpContext.Connection.RemoteIpAddress.ToString();
if (!string.IsNullOrEmpty(IPAddr))
{
StringDictionary badIPs = GetFileData(context, "BlockedIPs", config.IPBlacklistFile);
blocked |= (badIPs != null && badIPs.ContainsKey(IPAddr));
blockReason = $"This IP address ({IPAddr}) has been blacklisted. If you feel this is in error, please contact support@teknik.io for assistance.";
}
}
#endregion
#region Detect Blacklisted Referrers
if (!blocked)
{
string referrer = context.Request.Headers["Referer"].ToString();
string referrerHost = referrer;
try
{
var referrerUri = new Uri(referrer);
referrerHost = referrerUri.Host;
} catch
{ }
if (!string.IsNullOrEmpty(referrer))
{
StringDictionary badReferrers = GetFileData(context, "BlockedReferrers", config.ReferrerBlacklistFile);
if (badReferrers != null)
{
blocked |= badReferrers.ContainsKey(referrer) || badReferrers.ContainsKey(referrerHost);
blockReason = $"This referrer ({referrer}) has been blacklisted. If you feel this is in error, please contact support@teknik.io for assistance.";
}
}
}
#endregion
if (blocked)
{
// Clear the response
context.Response.Clear();
string jsonResult = JsonConvert.SerializeObject(new { error = new { type = "Blacklist", message = blockReason } });
await context.Response.WriteAsync(jsonResult);
return;
}
await _next.Invoke(context);
// End of request
}
public StringDictionary GetFileData(HttpContext context, string key, string filePath)
{
StringDictionary data;
if (!_cache.TryGetValue(key, out data))
{
data = GetFileLines(filePath);
_cache.Set(key, data);
}
return data;
}
public StringDictionary GetFileLines(string configPath)
{
StringDictionary retval = new StringDictionary();
if (File.Exists(configPath))
{
using (StreamReader sr = new StreamReader(configPath))
{
String line;
while ((line = sr.ReadLine()) != null)
{
line = line.Trim();
if (line.Length != 0)
{
retval.Add(line, null);
}
}
}
}
return retval;
}
}
public static class BlacklistMiddlewareExtensions
{
public static IApplicationBuilder UseBlacklist(this IApplicationBuilder builder)
{
return builder.UseMiddleware<BlacklistMiddleware>();
}
}
}

View File

@ -1,73 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Teknik.Configuration;
using Teknik.Utilities;
using Teknik.Utilities.Routing;
namespace Teknik.Middleware
{
// You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
public class CORSMiddleware
{
private readonly RequestDelegate _next;
public CORSMiddleware(RequestDelegate next)
{
_next = next;
}
public Task InvokeAsync(HttpContext httpContext, Config config)
{
// Allow this domain, or everything if local
string origin = (httpContext.Request.IsLocal()) ? "*" : httpContext.Request.Headers["Origin"].ToString();
// Is the referrer set to the CDN and we are using a CDN?
if (config.UseCdn && !string.IsNullOrEmpty(config.CdnHost))
{
try
{
string host = httpContext.Request.Headers["Host"];
Uri uri = new Uri(config.CdnHost);
if (host == uri.Host)
origin = host;
}
catch { }
}
string domain = (string.IsNullOrEmpty(origin)) ? string.Empty : origin.GetDomain();
if (string.IsNullOrEmpty(origin))
{
string host = httpContext.Request.Headers["Host"];
string sub = host.GetSubdomain();
origin = (string.IsNullOrEmpty(sub)) ? config.Host : sub + "." + config.Host;
}
else
{
if (domain != config.Host)
{
string sub = origin.GetSubdomain();
origin = (string.IsNullOrEmpty(sub)) ? config.Host : sub + "." + config.Host;
}
}
httpContext.Response.Headers.Append("Access-Control-Allow-Origin", origin);
httpContext.Response.Headers.Append("Vary", "Origin");
return _next(httpContext);
}
}
// Extension method used to add the middleware to the HTTP request pipeline.
public static class CORSMiddlewareExtensions
{
public static IApplicationBuilder UseCORS(this IApplicationBuilder builder)
{
return builder.UseMiddleware<CORSMiddleware>();
}
}
}

View File

@ -1,93 +0,0 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Teknik.Areas.Error.Controllers;
using Teknik.Configuration;
using Teknik.Data;
using Teknik.Logging;
using Teknik.Utilities;
namespace Teknik.Middleware
{
public class ErrorHandlerMiddleware
{
private readonly RequestDelegate _next;
public ErrorHandlerMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext, ILogger<Logger> logger, Config config, TeknikEntities dbContext, ErrorController errorController)
{
var statusCodeFeature = new StatusCodePagesFeature();
httpContext.Features.Set<IStatusCodePagesFeature>(statusCodeFeature);
Exception exception = null;
try
{
await _next(httpContext);
}
catch (Exception ex)
{
exception = ex;
}
if (!statusCodeFeature.Enabled)
{
// Check if the feature is still available because other middleware (such as a web API written in MVC) could
// have disabled the feature to prevent HTML status code responses from showing up to an API client.
return;
}
// Do nothing if a response body has already been provided or not 404 response
if (httpContext.Response.HasStarted)
{
return;
}
// Detect if there is a response code or exception occured
if ((httpContext.Response.StatusCode >= 400 && httpContext.Response.StatusCode <= 600) || exception != null)
{
var routeData = httpContext.GetRouteData() ?? new RouteData();
var context = new ControllerContext();
context.HttpContext = httpContext;
context.RouteData = routeData;
context.ActionDescriptor = new Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor();
errorController.ControllerContext = context;
if (httpContext.Response.StatusCode == 500 || exception != null)
{
await errorController.Http500(exception).ExecuteResultAsync(context);
}
else
{
await errorController.HttpError(httpContext.Response.StatusCode).ExecuteResultAsync(context);
}
}
}
}
// Extension method used to add the middleware to the HTTP request pipeline.
public static class SetupErrorHandlerMiddlewareExtensions
{
public static IApplicationBuilder UseErrorHandler(this IApplicationBuilder builder, Config config)
{
return builder.UseMiddleware<ErrorHandlerMiddleware>();
}
}
}

View File

@ -1,68 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Teknik.Configuration;
using Teknik.Utilities;
namespace Teknik.Middleware
{
// You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
public class PerformanceMonitorMiddleware
{
private readonly RequestDelegate _next;
public PerformanceMonitorMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext, Config config)
{
Stopwatch timer = new Stopwatch();
timer.Start();
httpContext.Response.OnStarting(state =>
{
var context = (HttpContext)state;
timer.Stop();
double ms = (double)timer.ElapsedMilliseconds;
string result = string.Format("{0:F0}", ms);
if (!httpContext.Response.Headers.IsReadOnly)
httpContext.Response.Headers.Add("GenerationTime", result);
return Task.CompletedTask;
}, httpContext);
await _next(httpContext);
// Don't interfere with non-HTML responses
if (httpContext.Response.ContentType != null && httpContext.Response.ContentType.StartsWith("text/html") && httpContext.Response.StatusCode == 200 && !httpContext.Request.IsAjaxRequest())
{
double ms = (double)timer.ElapsedMilliseconds;
string result = string.Format("{0:F0}", ms);
await httpContext.Response.WriteAsync(
"<script nonce=\"" + httpContext.Items[Constants.NONCE_KEY] + "\">" +
"var pageGenerationTime = '" + result + "';" +
"pageloadStopTimer();" +
"</script >");
}
}
}
// Extension method used to add the middleware to the HTTP request pipeline.
public static class PerformanceMonitorMiddlewareExtensions
{
public static IApplicationBuilder UsePerformanceMonitor(this IApplicationBuilder builder)
{
return builder.UseMiddleware<PerformanceMonitorMiddleware>();
}
}
}

View File

@ -1,53 +0,0 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Teknik.Configuration;
namespace Teknik.Middleware
{
public class SecurityHeadersMiddleware
{
private readonly RequestDelegate _next;
public SecurityHeadersMiddleware(RequestDelegate next)
{
_next = next;
}
public Task Invoke(HttpContext httpContext, Config config)
{
IHeaderDictionary headers = httpContext.Response.Headers;
// Access Control
headers.Append("Access-Control-Allow-Credentials", "true");
headers.Append("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS");
headers.Append("Access-Control-Allow-Headers", "Authorization, Accept, Origin, Content-Type, X-Requested-With, Connection, Transfer-Encoding");
// HSTS
headers.Append("strict-transport-security", "max-age=31536000; includeSubdomains; preload");
// XSS Protection
headers.Append("X-XSS-Protection", "1; mode=block");
// Content Type Options
headers.Append("X-Content-Type-Options", "nosniff");
// Referrer Policy
headers.Append("Referrer-Policy", "no-referrer, strict-origin-when-cross-origin");
return _next(httpContext);
}
}
// Extension method used to add the middleware to the HTTP request pipeline.
public static class SecurityHeadersMiddlewareExtensions
{
public static IApplicationBuilder UseSecurityHeaders(this IApplicationBuilder builder)
{
return builder.UseMiddleware<SecurityHeadersMiddleware>();
}
}
}

View File

@ -1,42 +0,0 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Teknik.Configuration;
using Teknik.Utilities;
namespace Teknik.Middleware
{
public class SetupHttpContextMiddleware
{
private readonly RequestDelegate _next;
public SetupHttpContextMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext, Config config)
{
// Setup the HTTP Context for everything else
// Generate the NONCE used for this request
string nonce = Convert.ToBase64String(Encoding.UTF8.GetBytes(StringHelper.RandomString(24)));
httpContext.Items[Constants.NONCE_KEY] = nonce;
await _next(httpContext);
}
}
// Extension method used to add the middleware to the HTTP request pipeline.
public static class SetupHttpContextMiddlewareExtensions
{
public static IApplicationBuilder UseHttpContextSetup(this IApplicationBuilder builder)
{
return builder.UseMiddleware<SetupHttpContextMiddleware>();
}
}
}

View File

@ -20,10 +20,10 @@ namespace Teknik
{ {
AppContext.SetSwitch("Microsoft.AspNetCore.Routing.UseCorrectCatchAllBehavior", AppContext.SetSwitch("Microsoft.AspNetCore.Routing.UseCorrectCatchAllBehavior",
true); true);
BuildWebHost(args).Build().Run(); CreateHostBuilder(args).Build().Run();
} }
public static IHostBuilder BuildWebHost(string[] args) public static IHostBuilder CreateHostBuilder(string[] args)
{ {
return Host.CreateDefaultBuilder(args) return Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(config => .ConfigureAppConfiguration(config =>
@ -42,18 +42,6 @@ namespace Teknik
logging.AddProvider(new LoggerProvider(Config.Load(dataDir))); logging.AddProvider(new LoggerProvider(Config.Load(dataDir)));
logging.AddFilter<ConsoleLoggerProvider>("Microsoft.AspNetCore.Routing", LogLevel.Trace); logging.AddFilter<ConsoleLoggerProvider>("Microsoft.AspNetCore.Routing", LogLevel.Trace);
}); });
/*
.UseConfiguration(config)
.UseIISIntegration()
.UseStartup<Startup>()
.ConfigureLogging((hostingContext, logging) =>
{
string baseDir = hostingContext.HostingEnvironment.ContentRootPath;
string dataDir = Path.Combine(baseDir, "App_Data");
logging.AddProvider(new LoggerProvider(Config.Load(dataDir)));
});
*/
} }
} }
} }

View File

@ -26,6 +26,9 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Teknik.Logging; using Teknik.Logging;
using Teknik.Utilities.Routing; using Teknik.Utilities.Routing;
using Teknik.WebCommon.Middleware;
using Teknik.WebCommon;
using Teknik.Areas.Error.Controllers;
namespace Teknik namespace Teknik
{ {
@ -63,8 +66,16 @@ namespace Teknik
// Resolve the services from the service provider // Resolve the services from the service provider
var config = sp.GetService<Config>(); var config = sp.GetService<Config>();
var devEnv = config?.DevEnvironment ?? true;
var defaultConn = config?.DbConnection ?? string.Empty;
var authority = config?.UserConfig?.IdentityServerConfig?.Authority ?? string.Empty;
var host = config?.Host ?? string.Empty;
var apiName = config?.UserConfig?.IdentityServerConfig?.APIName ?? string.Empty;
var apiSecret = config?.UserConfig?.IdentityServerConfig?.APISecret ?? string.Empty;
var clientId = config?.UserConfig?.IdentityServerConfig?.ClientId ?? string.Empty;
var clientSecret = config?.UserConfig?.IdentityServerConfig?.ClientSecret ?? string.Empty;
if (config.DevEnvironment) if (devEnv)
{ {
Environment.EnvironmentName = Environments.Development; Environment.EnvironmentName = Environments.Development;
} }
@ -88,6 +99,7 @@ namespace Teknik
services.AddHostedService<TrackingService>(); services.AddHostedService<TrackingService>();
services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>(); services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();
services.AddScoped<IErrorController, ErrorController>();
// Add Tracking Filter scopes // Add Tracking Filter scopes
//services.AddScoped<TrackDownload>(); //services.AddScoped<TrackDownload>();
@ -97,7 +109,7 @@ namespace Teknik
// Create the Database Context // Create the Database Context
services.AddDbContext<TeknikEntities>(options => options services.AddDbContext<TeknikEntities>(options => options
.UseLazyLoadingProxies() .UseLazyLoadingProxies()
.UseSqlServer(config.DbConnection), ServiceLifetime.Transient); .UseSqlServer(defaultConn), ServiceLifetime.Transient);
// Cookie Policies // Cookie Policies
services.Configure<CookiePolicyOptions>(options => services.Configure<CookiePolicyOptions>(options =>
@ -109,7 +121,7 @@ namespace Teknik
services.ConfigureApplicationCookie(options => services.ConfigureApplicationCookie(options =>
{ {
options.Cookie.Domain = CookieHelper.GenerateCookieDomain(config.Host, false, Environment.IsDevelopment()); options.Cookie.Domain = CookieHelper.GenerateCookieDomain(host, false, Environment.IsDevelopment());
options.Cookie.Name = "TeknikWeb"; options.Cookie.Name = "TeknikWeb";
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict; options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
@ -136,7 +148,7 @@ namespace Teknik
// Set the anti-forgery cookie name // Set the anti-forgery cookie name
services.AddAntiforgery(options => services.AddAntiforgery(options =>
{ {
options.Cookie.Domain = CookieHelper.GenerateCookieDomain(config.Host, false, Environment.IsDevelopment()); options.Cookie.Domain = CookieHelper.GenerateCookieDomain(host, false, Environment.IsDevelopment());
options.Cookie.Name = "TeknikWebAntiForgery"; options.Cookie.Name = "TeknikWebAntiForgery";
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict; options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
@ -151,11 +163,11 @@ namespace Teknik
}) })
.AddIdentityServerAuthentication(options => .AddIdentityServerAuthentication(options =>
{ {
options.Authority = config.UserConfig.IdentityServerConfig.Authority; options.Authority = authority;
options.RequireHttpsMetadata = true; options.RequireHttpsMetadata = true;
options.ApiName = config.UserConfig.IdentityServerConfig.APIName; options.ApiName = apiName;
options.ApiSecret = config.UserConfig.IdentityServerConfig.APISecret; options.ApiSecret = apiSecret;
options.NameClaimType = "username"; options.NameClaimType = "username";
options.RoleClaimType = JwtClaimTypes.Role; options.RoleClaimType = JwtClaimTypes.Role;
@ -166,7 +178,7 @@ namespace Teknik
options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict; options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
options.ExpireTimeSpan = TimeSpan.FromDays(30); options.ExpireTimeSpan = TimeSpan.FromDays(30);
options.Cookie.Name = "TeknikWebAuth"; options.Cookie.Name = "TeknikWebAuth";
options.Cookie.Domain = CookieHelper.GenerateCookieDomain(config.Host, false, Environment.IsDevelopment()); options.Cookie.Domain = CookieHelper.GenerateCookieDomain(host, false, Environment.IsDevelopment());
options.EventsType = typeof(CookieEventHandler); options.EventsType = typeof(CookieEventHandler);
}) })
@ -174,11 +186,11 @@ namespace Teknik
{ {
options.SignInScheme = "Cookies"; options.SignInScheme = "Cookies";
options.Authority = config.UserConfig.IdentityServerConfig.Authority; options.Authority = authority;
options.RequireHttpsMetadata = true; options.RequireHttpsMetadata = true;
options.ClientId = config.UserConfig.IdentityServerConfig.ClientId; options.ClientId = clientId;
options.ClientSecret = config.UserConfig.IdentityServerConfig.ClientSecret; options.ClientSecret = clientSecret;
options.ResponseType = "code id_token"; options.ResponseType = "code id_token";
// Set the scopes to listen to // Set the scopes to listen to
@ -255,8 +267,11 @@ namespace Teknik
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, TeknikEntities dbContext, Config config) public void Configure(IApplicationBuilder app, TeknikEntities dbContext, Config config)
{ {
var host = config?.Host ?? string.Empty;
var shortHost = config?.ShortenerConfig?.ShortenerHost ?? string.Empty;
// Create and Migrate the database // Create and Migrate the database
dbContext.Database.Migrate(); dbContext?.Database?.Migrate();
// Setup static files and cache them client side // Setup static files and cache them client side
app.UseStaticFiles(new StaticFileOptions app.UseStaticFiles(new StaticFileOptions
@ -279,7 +294,7 @@ namespace Teknik
IdleTimeout = TimeSpan.FromMinutes(30), IdleTimeout = TimeSpan.FromMinutes(30),
Cookie = new CookieBuilder() Cookie = new CookieBuilder()
{ {
Domain = CookieHelper.GenerateCookieDomain(config.Host, false, Environment.IsDevelopment()), Domain = CookieHelper.GenerateCookieDomain(host, false, Environment.IsDevelopment()),
Name = "TeknikWebSession", Name = "TeknikWebSession",
SecurePolicy = CookieSecurePolicy.SameAsRequest, SecurePolicy = CookieSecurePolicy.SameAsRequest,
SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict
@ -296,7 +311,7 @@ namespace Teknik
app.UseHttpsRedirection(); app.UseHttpsRedirection();
// Use Exception Handling // Use Exception Handling
app.UseErrorHandler(config); app.UseErrorHandler();
// Performance Monitor the entire request // Performance Monitor the entire request
app.UsePerformanceMonitor(); app.UsePerformanceMonitor();
@ -317,7 +332,7 @@ namespace Teknik
// And finally, let's use MVC // And finally, let's use MVC
app.UseEndpoints(endpoints => app.UseEndpoints(endpoints =>
{ {
endpoints.BuildEndpoints(config.Host, config.ShortenerConfig?.ShortenerHost); endpoints.BuildEndpoints(host, shortHost);
}); });
} }

View File

@ -97,6 +97,7 @@
<ProjectReference Include="..\MailService\MailService.csproj" /> <ProjectReference Include="..\MailService\MailService.csproj" />
<ProjectReference Include="..\Tracking\Tracking.csproj" /> <ProjectReference Include="..\Tracking\Tracking.csproj" />
<ProjectReference Include="..\Utilities\Utilities.csproj" /> <ProjectReference Include="..\Utilities\Utilities.csproj" />
<ProjectReference Include="..\WebCommon\WebCommon.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -135,8 +136,4 @@
<ProjectExtensions><VisualStudio><UserProperties /></VisualStudio></ProjectExtensions> <ProjectExtensions><VisualStudio><UserProperties /></VisualStudio></ProjectExtensions>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="npm run build" />
</Target>
</Project> </Project>

View File

@ -41,7 +41,7 @@
"plugin-error": "^1.0.1", "plugin-error": "^1.0.1",
"pump": "^3.0.0", "pump": "^3.0.0",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"uglify-es": "^3.3.9" "uglify-es": "^3.3.10"
}, },
"keywords": [ "keywords": [
"Teknik", "Teknik",
@ -54,7 +54,7 @@
"name": "teknik", "name": "teknik",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://git.teknik.io/Teknikode/TeknikCore" "url": "https://git.teknik.io/Teknikode/Teknik"
}, },
"scripts": { "scripts": {
"pre-publish": "npm install && gulp clean && gulp copy-assets && gulp watch", "pre-publish": "npm install && gulp clean && gulp copy-assets && gulp watch",