Browse Source

Migrated to .NET Core 5.0

tags/5.0.0
Teknikode 5 months ago
parent
commit
f5f2f4da86
55 changed files with 1574 additions and 1061 deletions
  1. 2
    2
      Configuration/Configuration.csproj
  2. 2
    2
      ContentScanningService/ContentScanningService.csproj
  3. 3
    3
      GitService/GitService.csproj
  4. 8
    7
      IdentityServer/IdentityServer.csproj
  5. 1
    7
      IdentityServer/Middleware/ErrorHandlerMiddleware.cs
  6. 2
    2
      Logging/Logging.csproj
  7. 2
    2
      MailService/MailService.csproj
  8. 1
    1
      ServiceWorker/ServiceWorker.csproj
  9. 1
    2
      Teknik.sln
  10. 12
    0
      Teknik/.config/dotnet-tools.json
  11. 1137
    0
      Teknik/App_Data/endpointMappings.json
  12. 1
    0
      Teknik/Areas/API/APIController.cs
  13. 1
    0
      Teknik/Areas/API/V1/Controllers/PasteAPIv1Controller.cs
  14. 1
    0
      Teknik/Areas/API/V1/Controllers/ShortenAPIv1Controller.cs
  15. 1
    0
      Teknik/Areas/API/V1/Controllers/UploadAPIv1Controller.cs
  16. 1
    0
      Teknik/Areas/Blog/Controllers/BlogController.cs
  17. 1
    0
      Teknik/Areas/Dev/Controllers/DevController.cs
  18. 1
    0
      Teknik/Areas/Paste/Controllers/PasteController.cs
  19. 1
    0
      Teknik/Areas/RSS/Controllers/RSSController.cs
  20. 1
    0
      Teknik/Areas/Shortener/Controllers/ShortenerController.cs
  21. 2
    1
      Teknik/Areas/Upload/Controllers/UploadController.cs
  22. 7
    0
      Teknik/Areas/Upload/UploadHelper.cs
  23. 1
    0
      Teknik/Areas/User/Controllers/UserController.cs
  24. 15
    8
      Teknik/Areas/User/Utility/IdentityHelper.cs
  25. 1
    0
      Teknik/Areas/User/Utility/UserHelper.cs
  26. 1
    0
      Teknik/Areas/Vault/Controllers/VaultController.cs
  27. 3
    3
      Teknik/Controllers/DefaultController.cs
  28. 6
    6
      Teknik/Data/TeknikEntities.cs
  29. 1
    0
      Teknik/Filters/TrackPageView.cs
  30. 1
    0
      Teknik/Middleware/CORSMiddleware.cs
  31. 1
    0
      Teknik/Middleware/CSPMiddleware.cs
  32. 4
    17
      Teknik/Middleware/ErrorHandlerMiddleware.cs
  33. 26
    9
      Teknik/Program.cs
  34. 2
    2
      Teknik/Properties/PublishProfiles/Teknik - Development.pubxml
  35. 2
    2
      Teknik/Properties/launchSettings.json
  36. 0
    844
      Teknik/Routes.cs
  37. 32
    40
      Teknik/Startup.cs
  38. 26
    16
      Teknik/Teknik.csproj
  39. 1
    1
      Teknik/Views/Shared/_Footer.cshtml
  40. 2
    1
      Teknik/_ViewImports.cshtml
  41. 3
    3
      Tracking/Tracking.csproj
  42. 2
    2
      Utilities/BufferedFileStreamResult.cs
  43. 1
    0
      Utilities/Constants.cs
  44. 1
    1
      Utilities/FileHelper.cs
  45. 7
    6
      Utilities/IdentityClientScope.cs
  46. 100
    0
      Utilities/Routing/EndpointHelper.cs
  47. 18
    0
      Utilities/Routing/EndpointMapping.cs
  48. 13
    0
      Utilities/Routing/HostType.cs
  49. 78
    0
      Utilities/Routing/SubdomainEndpointExtension.cs
  50. 1
    1
      Utilities/Routing/SubdomainRoute.cs
  51. 1
    1
      Utilities/Routing/SubdomainRouteExtension.cs
  52. 23
    58
      Utilities/Routing/UrlExtensions.cs
  53. 2
    3
      Utilities/TagHelpers/BundleTagHelper.cs
  54. 9
    7
      Utilities/Utilities.csproj
  55. 1
    1
      global.json

+ 2
- 2
Configuration/Configuration.csproj View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace>Teknik.Configuration</RootNamespace>
<AssemblyName>Teknik.Configuration</AssemblyName>
<RuntimeIdentifiers>win-x86;win-x64;linux-x64;linux-arm;osx-x64</RuntimeIdentifiers>
@@ -9,7 +9,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>

<ItemGroup>

+ 2
- 2
ContentScanningService/ContentScanningService.csproj View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>Teknik.ContentScanningService</AssemblyName>
<RootNamespace>Teknik.ContentScanningService</RootNamespace>
<RuntimeIdentifiers>win-x86;win-x64;linux-x64;linux-arm;osx-x64</RuntimeIdentifiers>
@@ -9,7 +9,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="nClam" Version="4.0.1" />
<PackageReference Include="nClam" Version="5.0.1" />
</ItemGroup>

<ItemGroup>

+ 3
- 3
GitService/GitService.csproj View File

@@ -1,15 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>Teknik.GitService</AssemblyName>
<RootNamespace>Teknik.GitService</RootNamespace>
<RuntimeIdentifiers>win-x86;win-x64;linux-x64;linux-arm;osx-x64</RuntimeIdentifiers>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="MySql.Data" Version="8.0.13" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="MySql.Data" Version="8.0.25" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>

</Project>

+ 8
- 7
IdentityServer/IdentityServer.csproj View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>Teknik.IdentityServer</AssemblyName>
<RootNamespace>Teknik.IdentityServer</RootNamespace>
<RuntimeIdentifiers>win-x86;win-x64;linux-x64;linux-arm;osx-x64</RuntimeIdentifiers>
@@ -15,12 +15,13 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="IdentityServer4" Version="2.5.1" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.7.0" />
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="2.5.1" />
<PackageReference Include="IdentityServer4.EntityFramework" Version="2.5.1" />
<PackageReference Include="Microsoft.AspNetCore.All" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.3" />
<PackageReference Include="IdentityServer4" Version="4.1.2" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="4.1.2" />
<PackageReference Include="IdentityServer4.EntityFramework" Version="4.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="5.0.2" />
</ItemGroup>

<ItemGroup>

+ 1
- 7
IdentityServer/Middleware/ErrorHandlerMiddleware.cs View File

@@ -3,7 +3,6 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@@ -94,12 +93,7 @@ namespace Teknik.IdentityServer.Middleware
{
public static IApplicationBuilder UseErrorHandler(this IApplicationBuilder builder, Config config)
{
var routes = new RouteBuilder(builder)
{
DefaultHandler = builder.ApplicationServices.GetRequiredService<MvcRouteHandler>(),
};

return builder.UseMiddleware<ErrorHandlerMiddleware>(routes.Build());
return builder.UseMiddleware<ErrorHandlerMiddleware>();
}
}
}

+ 2
- 2
Logging/Logging.csproj View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>Teknik.Logging</AssemblyName>
<RootNamespace>Teknik.Logging</RootNamespace>
<RuntimeIdentifiers>win-x86;win-x64;linux-x64;linux-arm;osx-x64</RuntimeIdentifiers>
@@ -9,7 +9,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
</ItemGroup>

<ItemGroup>

+ 2
- 2
MailService/MailService.csproj View File

@@ -1,14 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>Teknik.MailService</AssemblyName>
<RootNamespace>Teknik.MailService</RootNamespace>
<RuntimeIdentifiers>win-x86;win-x64;linux-x64;linux-arm;osx-x64</RuntimeIdentifiers>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="MySql.Data" Version="8.0.13" />
<PackageReference Include="MySql.Data" Version="8.0.25" />
</ItemGroup>

<ItemGroup>

+ 1
- 1
ServiceWorker/ServiceWorker.csproj View File

@@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace>Teknik.ServiceWorker</RootNamespace>
<AssemblyName>Teknik.ServiceWorker</AssemblyName>
</PropertyGroup>

+ 1
- 2
Teknik.sln View File

@@ -17,7 +17,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.gitattributes = .gitattributes
.gitignore = .gitignore
global.json = global.json
Performance1.psess = Performance1.psess
README.md = README.md
EndProjectSection
EndProject
@@ -31,7 +30,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServiceWorker", "ServiceWor
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IdentityServer", "IdentityServer\IdentityServer.csproj", "{3434645B-B8B4-457A-8C85-342E6727CCEE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContentScanningService", "ContentScanningService\ContentScanningService.csproj", "{491FE626-ABC8-4D00-8C7F-0849C357201A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ContentScanningService", "ContentScanningService\ContentScanningService.csproj", "{491FE626-ABC8-4D00-8C7F-0849C357201A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

+ 12
- 0
Teknik/.config/dotnet-tools.json View File

@@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "5.0.7",
"commands": [
"dotnet-ef"
]
}
}
}

+ 1137
- 0
Teknik/App_Data/endpointMappings.json
File diff suppressed because it is too large
View File


+ 1
- 0
Teknik/Areas/API/APIController.cs View File

@@ -14,6 +14,7 @@ using Teknik.Configuration;
using Teknik.Data;
using Microsoft.AspNetCore.Mvc;
using Teknik.Logging;
using Teknik.Utilities.Routing;

namespace Teknik.Areas.API.Controllers
{

+ 1
- 0
Teknik/Areas/API/V1/Controllers/PasteAPIv1Controller.cs View File

@@ -15,6 +15,7 @@ using Teknik.Data;
using Teknik.Filters;
using Teknik.Logging;
using Teknik.Utilities;
using Teknik.Utilities.Routing;

namespace Teknik.Areas.API.V1.Controllers
{

+ 1
- 0
Teknik/Areas/API/V1/Controllers/ShortenAPIv1Controller.cs View File

@@ -16,6 +16,7 @@ using Teknik.Data;
using Teknik.Filters;
using Teknik.Logging;
using Teknik.Utilities;
using Teknik.Utilities.Routing;

namespace Teknik.Areas.API.V1.Controllers
{

+ 1
- 0
Teknik/Areas/API/V1/Controllers/UploadAPIv1Controller.cs View File

@@ -21,6 +21,7 @@ using Teknik.Data;
using Teknik.Filters;
using Teknik.Logging;
using Teknik.Utilities;
using Teknik.Utilities.Routing;

namespace Teknik.Areas.API.V1.Controllers
{

+ 1
- 0
Teknik/Areas/Blog/Controllers/BlogController.cs View File

@@ -20,6 +20,7 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Teknik.Logging;
using Teknik.Utilities.Routing;

namespace Teknik.Areas.Blog.Controllers
{

+ 1
- 0
Teknik/Areas/Dev/Controllers/DevController.cs View File

@@ -8,6 +8,7 @@ using Teknik.Data;
using Teknik.Filters;
using Teknik.Utilities;
using Teknik.Logging;
using Teknik.Utilities.Routing;

namespace Teknik.Areas.Dev.Controllers
{

+ 1
- 0
Teknik/Areas/Paste/Controllers/PasteController.cs View File

@@ -21,6 +21,7 @@ using Teknik.Logging;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Diagnostics;
using Teknik.Utilities.Routing;

namespace Teknik.Areas.Paste.Controllers
{

+ 1
- 0
Teknik/Areas/RSS/Controllers/RSSController.cs View File

@@ -22,6 +22,7 @@ using System.Text;
using System.Threading.Tasks;
using Microsoft.SyndicationFeed;
using Teknik.Logging;
using Teknik.Utilities.Routing;

namespace Teknik.Areas.RSS.Controllers
{

+ 1
- 0
Teknik/Areas/Shortener/Controllers/ShortenerController.cs View File

@@ -14,6 +14,7 @@ using Teknik.Data;
using Teknik.Filters;
using Teknik.Logging;
using Teknik.Utilities;
using Teknik.Utilities.Routing;

namespace Teknik.Areas.Shortener.Controllers
{

+ 2
- 1
Teknik/Areas/Upload/Controllers/UploadController.cs View File

@@ -23,6 +23,7 @@ using Microsoft.AspNetCore.Http;
using Teknik.Logging;
using Teknik.Areas.Users.Models;
using Teknik.ContentScanningService;
using Teknik.Utilities.Routing;

namespace Teknik.Areas.Upload.Controllers
{
@@ -259,7 +260,7 @@ namespace Teknik.Areas.Upload.Controllers
IdentityUserInfo userInfo = await IdentityHelper.GetIdentityUserInfo(_config, User.Identity.Name);
premiumAccount = userInfo.AccountType == AccountType.Premium;
}
if (!premiumAccount && upload.User != null)
if (!premiumAccount && upload.UserId != null)
{
IdentityUserInfo userInfo = await IdentityHelper.GetIdentityUserInfo(_config, upload.User.Username);
premiumAccount = userInfo.AccountType == AccountType.Premium;

+ 7
- 0
Teknik/Areas/Upload/UploadHelper.cs View File

@@ -135,5 +135,12 @@ namespace Teknik.Areas.Upload

return false;
}

public static Models.Upload GetUpload(TeknikEntities db, string url)
{
Models.Upload upload = db.Uploads.Where(up => up.Url == url).FirstOrDefault();

return upload;
}
}
}

+ 1
- 0
Teknik/Areas/User/Controllers/UserController.cs View File

@@ -36,6 +36,7 @@ using System.Security.Cryptography;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.AspNetCore.Http;
using IdentityServer4.Models;
using Teknik.Utilities.Routing;

namespace Teknik.Areas.Users.Controllers
{

+ 15
- 8
Teknik/Areas/User/Utility/IdentityHelper.cs View File

@@ -15,18 +15,24 @@ namespace Teknik.Areas.Users.Utility
{
public static class IdentityHelper
{
public static async Task<string> GetAccessToken(Config config)
public static async Task GetAccessToken(this HttpClient client, Config config)
{
return await GetAccessToken(config.UserConfig.IdentityServerConfig.Authority, config.UserConfig.IdentityServerConfig.ClientId, config.UserConfig.IdentityServerConfig.ClientSecret, "auth-api");
var token = await client.GetAccessToken(config.UserConfig.IdentityServerConfig.Authority, config.UserConfig.IdentityServerConfig.ClientId, config.UserConfig.IdentityServerConfig.ClientSecret, "auth-api");
client.SetBearerToken(token);
}

public static async Task<string> GetAccessToken(string authority, string clientId, string secret, string scope)
public static async Task<string> GetAccessToken(this HttpClient client, string authority, string clientId, string secret, string scope)
{
var disco = await DiscoveryClient.GetAsync(authority);
var disco = await client.GetDiscoveryDocumentAsync(authority);
if (disco.IsError) throw new Exception(disco.Error);

var tokenClient = new TokenClient(disco.TokenEndpoint, clientId, secret);
var tokenResponse = await tokenClient.RequestClientCredentialsAsync(scope);
var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = clientId,
ClientSecret = secret,
Scope = scope
});

if (tokenResponse.IsError) throw new Exception(tokenResponse.Error);

@@ -42,7 +48,7 @@ namespace Teknik.Areas.Users.Utility
public static async Task<IdentityResult> Get(Config config, Uri url)
{
var client = new HttpClient();
client.SetBearerToken(await GetAccessToken(config));
await client.GetAccessToken(config);

var content = await client.GetStringAsync(url);
if (!string.IsNullOrEmpty(content))
@@ -56,7 +62,8 @@ namespace Teknik.Areas.Users.Utility
public static async Task<IdentityResult> Post(Config config, Uri url, object data)
{
var client = new HttpClient();
client.SetBearerToken(await GetAccessToken(config));
await client.GetAccessToken(config);


var response = await client.PostAsJsonAsync(url, data);
if (response.IsSuccessStatusCode)

+ 1
- 0
Teknik/Areas/User/Utility/UserHelper.cs View File

@@ -32,6 +32,7 @@ using System.Net.Http;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using Microsoft.AspNetCore.Mvc;
using Teknik.Utilities.Routing;

namespace Teknik.Areas.Users.Utility
{

+ 1
- 0
Teknik/Areas/Vault/Controllers/VaultController.cs View File

@@ -24,6 +24,7 @@ using Teknik.Logging;
using Teknik.Models;
using Teknik.Utilities;
using Teknik.Utilities.Cryptography;
using Teknik.Utilities.Routing;

namespace Teknik.Areas.Vault.Controllers
{

+ 3
- 3
Teknik/Controllers/DefaultController.cs View File

@@ -52,7 +52,7 @@ namespace Teknik.Controllers
[HttpGet]
[AllowAnonymous]
[ResponseCache(Duration = 31536000, Location = ResponseCacheLocation.Any)]
public IActionResult Favicon([FromServices] IHostingEnvironment env)
public IActionResult Favicon([FromServices] IWebHostEnvironment env)
{
string imageFile = FileHelper.MapPath(env, Constants.FAVICON_PATH);
FileStream fs = new FileStream(imageFile, FileMode.Open, FileAccess.Read);
@@ -63,7 +63,7 @@ namespace Teknik.Controllers
[HttpGet]
[AllowAnonymous]
[ResponseCache(Duration = 31536000, Location = ResponseCacheLocation.Any)]
public IActionResult Logo([FromServices] IHostingEnvironment env)
public IActionResult Logo([FromServices] IWebHostEnvironment env)
{
string imageFile = FileHelper.MapPath(env, Constants.LOGO_PATH);
FileStream fs = new FileStream(imageFile, FileMode.Open, FileAccess.Read);
@@ -73,7 +73,7 @@ namespace Teknik.Controllers
// Get the Robots.txt
[HttpGet]
[AllowAnonymous]
public IActionResult Robots([FromServices] IHostingEnvironment env)
public IActionResult Robots([FromServices] IWebHostEnvironment env)
{
string dataDir = (string)AppDomain.CurrentDomain.GetData("DataDirectory");
string file = Path.Combine(dataDir, Constants.ROBOTS_PATH);

+ 6
- 6
Teknik/Data/TeknikEntities.cs View File

@@ -69,9 +69,9 @@ namespace Teknik.Data
// User
modelBuilder.Entity<User>()
.HasKey(u => u.UserId);
modelBuilder.Entity<User>().OwnsOne(u => u.UserSettings);
modelBuilder.Entity<User>().OwnsOne(u => u.BlogSettings);
modelBuilder.Entity<User>().OwnsOne(u => u.UploadSettings);
modelBuilder.Entity<User>().OwnsOne(u => u.UserSettings, us => us.ToTable("Users"));
modelBuilder.Entity<User>().OwnsOne(u => u.BlogSettings, bs => bs.ToTable("Users"));
modelBuilder.Entity<User>().OwnsOne(u => u.UploadSettings, us => us.ToTable("Users"));
modelBuilder.Entity<User>().HasMany(u => u.Features).WithOne(u => u.User);
modelBuilder.Entity<User>().HasMany(u => u.Uploads).WithOne(u => u.User);
modelBuilder.Entity<User>().HasMany(u => u.Pastes).WithOne(u => u.User);
@@ -116,9 +116,9 @@ namespace Teknik.Data
modelBuilder.Entity<InviteCode>().ToTable("InviteCodes");
modelBuilder.Entity<UserFeature>().ToTable("UserFeatures");
// User Settings
modelBuilder.Entity<UserSettings>().ToTable("Users");
modelBuilder.Entity<BlogSettings>().ToTable("Users");
modelBuilder.Entity<UploadSettings>().ToTable("Users");
//modelBuilder.Entity<UserSettings>().ToTable("Users");
//modelBuilder.Entity<BlogSettings>().ToTable("Users");
//modelBuilder.Entity<UploadSettings>().ToTable("Users");
// Features
modelBuilder.Entity<Feature>().ToTable("Features");
// Blogs

+ 1
- 0
Teknik/Filters/TrackPageView.cs View File

@@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Teknik.Utilities.Routing;

namespace Teknik.Filters
{

+ 1
- 0
Teknik/Middleware/CORSMiddleware.cs View File

@@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Teknik.Configuration;
using Teknik.Utilities;
using Teknik.Utilities.Routing;

namespace Teknik.Middleware
{

+ 1
- 0
Teknik/Middleware/CSPMiddleware.cs View File

@@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Teknik.Configuration;
using Teknik.Utilities;
using Teknik.Utilities.Routing;

namespace Teknik.Middleware
{

+ 4
- 17
Teknik/Middleware/ErrorHandlerMiddleware.cs View File

@@ -2,7 +2,6 @@
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@@ -25,15 +24,13 @@ namespace Teknik.Middleware
public class ErrorHandlerMiddleware
{
private readonly RequestDelegate _next;
private readonly IRouter _router;

public ErrorHandlerMiddleware(RequestDelegate next, IRouter router)
public ErrorHandlerMiddleware(RequestDelegate next)
{
_next = next;
_router = router;
}

public async Task Invoke(HttpContext httpContext, ILogger<Logger> logger, Config config, TeknikEntities dbContext)
public async Task Invoke(HttpContext httpContext, ILogger<Logger> logger, Config config, TeknikEntities dbContext, ErrorController errorController)
{
var statusCodeFeature = new StatusCodePagesFeature();
httpContext.Features.Set<IStatusCodePagesFeature>(statusCodeFeature);
@@ -64,17 +61,13 @@ namespace Teknik.Middleware
// Detect if there is a response code or exception occured
if ((httpContext.Response.StatusCode >= 400 && httpContext.Response.StatusCode <= 600) || exception != null)
{
RouteData routeData = new RouteData();
routeData.DataTokens.Add("area", "Error");
routeData.Values.Add("controller", "Error");
routeData.Routers.Add(_router);
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 errorController = new ErrorController(logger, config, dbContext);
errorController.ControllerContext = context;

if (httpContext.Response.StatusCode == 500 || exception != null)
@@ -94,13 +87,7 @@ namespace Teknik.Middleware
{
public static IApplicationBuilder UseErrorHandler(this IApplicationBuilder builder, Config config)
{
var routes = new RouteBuilder(builder)
{
DefaultHandler = builder.ApplicationServices.GetRequiredService<MvcRouteHandler>(),
};
routes.BuildRoutes(config);

return builder.UseMiddleware<ErrorHandlerMiddleware>(routes.Build());
return builder.UseMiddleware<ErrorHandlerMiddleware>();
}
}
}

+ 26
- 9
Teknik/Program.cs View File

@@ -6,7 +6,9 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Console;
using Teknik.Configuration;
using Teknik.Logging;

@@ -16,17 +18,32 @@ namespace Teknik
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
AppContext.SetSwitch("Microsoft.AspNetCore.Routing.UseCorrectCatchAllBehavior",
true);
BuildWebHost(args).Build().Run();
}

public static IWebHost BuildWebHost(string[] args)
public static IHostBuilder BuildWebHost(string[] args)
{
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true)
.AddCommandLine(args)
.Build();
return Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(config =>
{
config.AddJsonFile("appsettings.json", optional: true);
config.AddCommandLine(args);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureLogging((hostingContext, logging) =>
{
string baseDir = hostingContext.HostingEnvironment.ContentRootPath;
string dataDir = Path.Combine(baseDir, "App_Data");
logging.AddProvider(new LoggerProvider(Config.Load(dataDir)));
logging.AddFilter<ConsoleLoggerProvider>("Microsoft.AspNetCore.Routing", LogLevel.Trace);
});

return WebHost.CreateDefaultBuilder(args)
/*
.UseConfiguration(config)
.UseIISIntegration()
.UseStartup<Startup>()
@@ -35,8 +52,8 @@ namespace Teknik
string baseDir = hostingContext.HostingEnvironment.ContentRootPath;
string dataDir = Path.Combine(baseDir, "App_Data");
logging.AddProvider(new LoggerProvider(Config.Load(dataDir)));
})
.Build();
});
*/
}
}
}

+ 2
- 2
Teknik/Properties/PublishProfiles/Teknik - Development.pubxml View File

@@ -8,10 +8,10 @@ by editing this MSBuild file. In order to learn more about this please visit htt
<WebPublishMethod>MSDeploy</WebPublishMethod>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish>https://dev.teknik.io/</SiteUrlToLaunchAfterPublish>
<SiteUrlToLaunchAfterPublish>https://dev.teknik.io/Home</SiteUrlToLaunchAfterPublish>
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<ExcludeApp_Data>True</ExcludeApp_Data>
<TargetFramework>netcoreapp2.2</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<ProjectGuid>1e52f0d0-9e89-4022-a905-c685ef3564e1</ProjectGuid>
<SelfContained>false</SelfContained>
<_IsPortable>true</_IsPortable>

+ 2
- 2
Teknik/Properties/launchSettings.json View File

@@ -11,7 +11,7 @@
"TeknikCore": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "?sub=www",
"launchUrl": "Home",
"environmentVariables": {
"ASPNETCORE_URLS": "https://localhost:8050",
"ASPNETCORE_ENVIRONMENT": "Development"
@@ -22,7 +22,7 @@
"launchBrowser": true,
"launchUrl": "?sub=www",
"environmentVariables": {
"ASPNETCORE_URLS": "https://localhost:5050",
"ASPNETCORE_URLS": "https://localhost:8050",
"ASPNETCORE_ENVIRONMENT": "Production"
}
},

+ 0
- 844
Teknik/Routes.cs View File

@@ -1,844 +0,0 @@
using Microsoft.AspNetCore.Routing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Teknik.Configuration;
using Teknik.Utilities;

namespace Teknik
{
public static class Routes
{
public static void BuildRoutes(this IRouteBuilder routes, Config config)
{
routes.BuildDefaultRoutes(config);
routes.BuildAboutRoutes(config);
routes.BuildAbuseRoutes(config);
routes.BuildAdminRoutes(config);
routes.BuildAPIRoutes(config);
routes.BuildBlogRoutes(config);
routes.BuildContactRoutes(config);
routes.BuildDevRoutes(config);
routes.BuildErrorRoutes(config);
routes.BuildFAQRoutes(config);
routes.BuildHelpRoutes(config);
routes.BuildHomeRoutes(config);
routes.BuildPasteRoutes(config);
routes.BuildPodcastRoutes(config);
routes.BuildPrivacyRoutes(config);
routes.BuildRSSRoutes(config);
routes.BuildShortenerRoutes(config);
routes.BuildStatsRoutes(config);
routes.BuildTOSRoutes(config);
routes.BuildUploadRoutes(config);
routes.BuildUserRoutes(config);
routes.BuildVaultRoutes(config);
}

public static void BuildDefaultRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "Default.Favicon",
domains: new List<string>() { config.Host, config.ShortenerConfig.ShortenerHost },
subDomains: new List<string>() { "*" },
template: "favicon.ico",
defaults: new { area = "Default", controller = "Default", action = "Favicon" }
);
routes.MapSubdomainRoute(
name: "Default.Logo",
domains: new List<string>() { config.Host, config.ShortenerConfig.ShortenerHost },
subDomains: new List<string>() { "*" },
template: "logo.svg",
defaults: new { area = "Default", controller = "Default", action = "Logo" }
);
routes.MapSubdomainRoute(
name: "Default.Robots",
domains: new List<string>() { config.Host, config.ShortenerConfig.ShortenerHost },
subDomains: new List<string>() { "*" },
template: "robots.txt",
defaults: new { area = "Default", controller = "Default", action = "Robots" }
);
routes.MapSubdomainRoute(
name: "Default.NotFound",
domains: new List<string>() { config.Host, config.ShortenerConfig.ShortenerHost },
subDomains: new List<string>() { "*" },
template: "{url}",
defaults: new { area = "Error", controller = "Error", action = "Http404" },
constraints: new { url = "{*url}" }
);
}

public static void BuildAboutRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "About.Index",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "about" },
template: "",
defaults: new { area = "About", controller = "About", action = "Index" }
);
}

public static void BuildAbuseRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "Abuse.Index",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "abuse" },
template: "",
defaults: new { area = "Abuse", controller = "Abuse", action = "Index" }
);
}

public static void BuildAdminRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "Admin.Dashboard",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "admin" },
template: "",
defaults: new { area = "Admin", controller = "Admin", action = "Dashboard" }
);
routes.MapSubdomainRoute(
name: "Admin.UserSearch",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "admin" },
template: "Search/Users",
defaults: new { area = "Admin", controller = "Admin", action = "UserSearch" }
);
routes.MapSubdomainRoute(
name: "Admin.UploadSearch",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "admin" },
template: "Search/Uploads",
defaults: new { area = "Admin", controller = "Admin", action = "UploadSearch" }
);
routes.MapSubdomainRoute(
name: "Admin.PasteSearch",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "admin" },
template: "Search/Pastes",
defaults: new { area = "Admin", controller = "Admin", action = "PasteSearch" }
);
routes.MapSubdomainRoute(
name: "Admin.ShortenedUrlSearch",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "admin" },
template: "Search/ShortenedUrls",
defaults: new { area = "Admin", controller = "Admin", action = "ShortenedUrlSearch" }
);
routes.MapSubdomainRoute(
name: "Admin.UserInfo",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "admin" },
template: "User/{username}",
defaults: new { area = "Admin", controller = "Admin", action = "UserInfo", username = string.Empty }
);
routes.MapSubdomainRoute(
name: "Admin.Action",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "admin" },
template: "Action/{action}",
defaults: new { area = "Admin", controller = "Admin", action = "Dashboard" }
);
}

public static void BuildAPIRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "API.v1.Claims",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "api" },
template: "v1/Claims",
defaults: new { area = "API", controller = "AccountAPIv1", action = "GetClaims" }
);
routes.MapSubdomainRoute(
name: "API.v1.Upload",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "api" },
template: "v1/Upload",
defaults: new { area = "API", controller = "UploadAPIv1", action = "Upload" }
);
routes.MapSubdomainRoute(
name: "API.v1.Paste",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "api" },
template: "v1/Paste",
defaults: new { area = "API", controller = "PasteAPIv1", action = "Paste" }
);
routes.MapSubdomainRoute(
name: "API.v1.Shorten",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "api" },
template: "v1/Shorten",
defaults: new { area = "API", controller = "ShortenAPIv1", action = "Shorten" }
);

routes.MapSubdomainRoute(
name: "API.Index",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "api" },
template: "",
defaults: new { area = "API", controller = "API", action = "Index" }
);
}

public static void BuildBlogRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "Blog.Blog",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "blog" },
template: "{username}",
defaults: new { area = "Blog", controller = "Blog", action = "Blog", username = string.Empty }
);
routes.MapSubdomainRoute(
name: "Blog.New",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "blog" },
template: "{username}/New",
defaults: new { area = "Blog", controller = "Blog", action = "NewPost", username = string.Empty }
);
routes.MapSubdomainRoute(
name: "Blog.Edit",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "blog" },
template: "{username}/Edit/{id}",
defaults: new { area = "Blog", controller = "Blog", action = "EditPost", username = string.Empty, id = -1 }
);
routes.MapSubdomainRoute(
name: "Blog.Post",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "blog" },
template: "{username}/p/{id}",
defaults: new { area = "Blog", controller = "Blog", action = "Post", username = string.Empty, id = -1 }
);
routes.MapSubdomainRoute(
name: "Blog.Action",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "blog" },
template: "Action/{action}",
defaults: new { area = "Blog", controller = "Blog", action = "Blog" }
);
}

public static void BuildContactRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "Contact.Index",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "contact" },
template: "",
defaults: new { area = "Contact", controller = "Contact", action = "Index" }
);
routes.MapSubdomainRoute(
name: "Contact.Action",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "contact" },
template: "Action/{action}",
defaults: new { area = "Contact", controller = "Contact", action = "Index" }
);
}

public static void BuildDevRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "Dev.Index",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "dev" },
template: "",
defaults: new { area = "Dev", controller = "Dev", action = "Index" }
);
}

public static void BuildErrorRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "Error.HttpError",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "error" },
template: "{statusCode:int}",
defaults: new { area = "Error", controller = "Error", action = "HttpError", statusCode = 500 }
);
routes.MapSubdomainRoute(
name: "Error.Http401",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "error" },
template: "401",
defaults: new { area = "Error", controller = "Error", action = "Http401" }
);
routes.MapSubdomainRoute(
name: "Error.Http403",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "error" },
template: "403",
defaults: new { area = "Error", controller = "Error", action = "Http403" }
);
routes.MapSubdomainRoute(
name: "Error.Http404",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "error" },
template: "404",
defaults: new { area = "Error", controller = "Error", action = "Http404" }
);
routes.MapSubdomainRoute(
name: "Error.Http500",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "error" },
template: "500",
defaults: new { area = "Error", controller = "Error", action = "Http500" }
);
routes.MapSubdomainRoute(
name: "Error.Action",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "error" },
template: "Action/{action}",
defaults: new { area = "Error", controller = "Error", action = "HttpError" }
);
}

public static void BuildFAQRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "FAQ.Index",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "faq" },
template: "",
defaults: new { area = "FAQ", controller = "FAQ", action = "Index" }
);
}

public static void BuildHelpRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "Help.Index",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "help" },
template: "",
defaults: new { area = "Help", controller = "Help", action = "Index" }
);
routes.MapSubdomainRoute(
name: "Help.API",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "help" },
template: "API/{version?}/{service?}",
defaults: new { area = "Help", controller = "Help", action = "API" }
);
routes.MapSubdomainRoute(
name: "Help.Blog",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "help" },
template: "Blog",
defaults: new { area = "Help", controller = "Help", action = "Blog" }
);
routes.MapSubdomainRoute(
name: "Help.Git",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "help" },
template: "Git",
defaults: new { area = "Help", controller = "Help", action = "Git" }
);
routes.MapSubdomainRoute(
name: "Help.IRC",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "help" },
template: "IRC",
defaults: new { area = "Help", controller = "Help", action = "IRC" }
);
routes.MapSubdomainRoute(
name: "Help.Mail",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "help" },
template: "Mail",
defaults: new { area = "Help", controller = "Help", action = "Mail" }
);
routes.MapSubdomainRoute(
name: "Help.Markdown",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "help" },
template: "Markdown",
defaults: new { area = "Help", controller = "Help", action = "Markdown" }
);
routes.MapSubdomainRoute(
name: "Help.Mumble",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "help" },
template: "Mumble",
defaults: new { area = "Help", controller = "Help", action = "Mumble" }
);
routes.MapSubdomainRoute(
name: "Help.RSS",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "help" },
template: "RSS",
defaults: new { area = "Help", controller = "Help", action = "RSS" }
);
routes.MapSubdomainRoute(
name: "Help.Tools",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "help" },
template: "Tools",
defaults: new { area = "Help", controller = "Help", action = "Tools" }
);
routes.MapSubdomainRoute(
name: "Help.Upload",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "help" },
template: "Upload",
defaults: new { area = "Help", controller = "Help", action = "Upload" }
);
}

public static void BuildHomeRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "Home.Index",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "www", string.Empty },
template: "",
defaults: new { area = "Home", controller = "Home", action = "Index" }
);
}

public static void BuildPasteRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "Paste.Index",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "paste", "p" },
template: "",
defaults: new { area = "Paste", controller = "Paste", action = "Index" }
);
routes.MapSubdomainRoute(
name: "Paste.Simple",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "paste", "p" },
template: "Simple/{url}/{password?}",
defaults: new { area = "Paste", controller = "Paste", action = "ViewPaste", type = "Simple" }
);
routes.MapSubdomainRoute(
name: "Paste.Raw",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "paste", "p" },
template: "Raw/{url}/{password?}",
defaults: new { area = "Paste", controller = "Paste", action = "ViewPaste", type = "Raw" }
);
routes.MapSubdomainRoute(
name: "Paste.Download",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "paste", "p" },
template: "Download/{url}/{password?}",
defaults: new { area = "Paste", controller = "Paste", action = "ViewPaste", type = "Download" }
);
routes.MapSubdomainRoute(
name: "Paste.Edit",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "paste", "p" },
template: "Edit/{url}/{password?}",
defaults: new { area = "Paste", controller = "Paste", action = "Edit" }
);
routes.MapSubdomainRoute(
name: "Paste.Delete",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "paste", "p" },
template: "Delete",
defaults: new { area = "Paste", controller = "Paste", action = "Delete" }
);
routes.MapSubdomainRoute(
name: "Paste.Action",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "paste", "p" },
template: "Action/{action}",
defaults: new { area = "Paste", controller = "Paste", action = "Index" }
);
routes.MapSubdomainRoute(
name: "Paste.View",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "paste", "p" },
template: "{url}/{password?}",
defaults: new { area = "Paste", controller = "Paste", action = "ViewPaste", type = "Full" }
);
}

public static void BuildPodcastRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "Podcast.Index",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "podcast" },
template: "",
defaults: new { area = "Podcast", controller = "Podcast", action = "Index" }
);
routes.MapSubdomainRoute(
name: "Podcast.View",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "podcast" },
template: "ep/{episode}",
defaults: new { area = "Podcast", controller = "Podcast", action = "View" }
);
routes.MapSubdomainRoute(
name: "Podcast.Download",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "podcast" },
template: "File/{episode}/{fileName}",
defaults: new { area = "Podcast", controller = "Podcast", action = "Download" }
);
routes.MapSubdomainRoute(
name: "Podcast.Action",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "podcast" },
template: "Action/{action}",
defaults: new { area = "Podcast", controller = "Podcast", action = "Index" }
);
}

public static void BuildPrivacyRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "Privacy.Index",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "privacy" },
template: "",
defaults: new { area = "Privacy", controller = "Privacy", action = "Index" }
);
}

public static void BuildRSSRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "RSS.Index",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "rss" },
template: "",
defaults: new { area = "RSS", controller = "RSS", action = "Index" }
);
routes.MapSubdomainRoute(
name: "RSS.Blog",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "rss" },
template: "Blog/{username?}",
defaults: new { area = "RSS", controller = "RSS", action = "Blog" }
);
routes.MapSubdomainRoute(
name: "RSS.Podcast",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "rss" },
template: "Podcast",
defaults: new { area = "RSS", controller = "RSS", action = "Podcast" }
);
}

public static void BuildShortenerRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "Shortener.Index",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "shorten", "s" },
template: "",
defaults: new { area = "Shortener", controller = "Shortener", action = "Index" }
);
routes.MapSubdomainRoute(
name: "Shortener.Delete",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "shorten", "s" },
template: "Delete",
defaults: new { area = "Shortener", controller = "Shortener", action = "Delete" }
);
routes.MapSubdomainRoute(
name: "Shortener.Action",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "shorten", "s" },
template: "Action/{action}",
defaults: new { area = "Shortener", controller = "Shortener", action = "Index" }
);
routes.MapSubdomainRoute(
name: "Shortener.View",
domains: new List<string>() { config.ShortenerConfig.ShortenerHost, config.Host },
subDomains: new List<string>() { string.Empty, "shortened" },
template: "{url}",
defaults: new { area = "Shortener", controller = "Shortener", action = "RedirectToUrl" }
);
routes.MapSubdomainRoute(
name: "Shortener.Verify",
domains: new List<string>() { config.ShortenerConfig.ShortenerHost },
subDomains: new List<string>() { string.Empty },
template: "",
defaults: new { area = "Shortener", controller = "Shortener", action = "Verify" }
);
}

public static void BuildStatsRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "Stats.Index",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "stats" },
template: "",
defaults: new { area = "Stats", controller = "Stats", action = "Index" }
);
routes.MapSubdomainRoute(
name: "Stats.Action",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "stats" },
template: "Action/{action}",
defaults: new { area = "Stats", controller = "Stats", action = "Index" }
);
}

public static void BuildTOSRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "TOS.Index",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "tos" },
template: "",
defaults: new { area = "TOS", controller = "TOS", action = "Index" }
);
}

public static void BuildUploadRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "Upload.Index",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "upload", "u" },
template: "",
defaults: new { area = "Upload", controller = "Upload", action = "Index" }
);
routes.MapSubdomainRoute(
name: "Upload.GenerateDeleteKey",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "upload", "u", "user" },
template: "GenerateDeleteKey",
defaults: new { area = "Upload", controller = "Upload", action = "GenerateDeleteKey" }
);
routes.MapSubdomainRoute(
name: "Upload.Delete",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "upload", "u" },
template: "Delete",
defaults: new { area = "Upload", controller = "Upload", action = "Delete" }
);
routes.MapSubdomainRoute(
name: "Upload.Download",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "upload", "u" },
template: "{file}",
defaults: new { area = "Upload", controller = "Upload", action = "Download" }
);
routes.MapSubdomainRoute(
name: "Upload.DeleteByKey",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "upload", "u" },
template: "{file}/{key}",
defaults: new { area = "Upload", controller = "Upload", action = "DeleteByKey" }
);
routes.MapSubdomainRoute(
name: "Upload.Action",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "upload", "u" },
template: "Action/{action}",
defaults: new { area = "Upload", controller = "Upload", action = "Index" }
);
}

public static void BuildUserRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "User.Index",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "account" },
template: "",
defaults: new { area = "User", controller = "User", action = "Index" }
);
routes.MapSubdomainRoute(
name: "User.GetPremium",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "account" },
template: "GetPremium",
defaults: new { area = "User", controller = "User", action = "GetPremium" }
);
routes.MapSubdomainRoute(
name: "User.Register",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "account" },
template: "Register",
defaults: new { area = "User", controller = "User", action = "Register" }
);
routes.MapSubdomainRoute(
name: "User.Login",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "account" },
template: "Login",
defaults: new { area = "User", controller = "User", action = "Login" }
);
routes.MapSubdomainRoute(
name: "User.Logout",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "account" },
template: "Logout",
defaults: new { area = "User", controller = "User", action = "Logout" }
);
routes.MapSubdomainRoute(
name: "User.Settings",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "account" },
template: "Settings",
defaults: new { area = "User", controller = "User", action = "Settings" }
);
routes.MapSubdomainRoute(
name: "User.AccountSettings",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "account" },
template: "Settings/Account",
defaults: new { area = "User", controller = "User", action = "AccountSettings" }
);
routes.MapSubdomainRoute(
name: "User.SecuritySettings",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "account" },
template: "Settings/Security",
defaults: new { area = "User", controller = "User", action = "SecuritySettings" }
);
routes.MapSubdomainRoute(
name: "User.ProfileSettings",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "account" },
template: "Settings/Profile",
defaults: new { area = "User", controller = "User", action = "ProfileSettings" }
);
routes.MapSubdomainRoute(
name: "User.DeveloperSettings",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "account" },
template: "Settings/Developer",
defaults: new { area = "User", controller = "User", action = "DeveloperSettings" }
);
routes.MapSubdomainRoute(
name: "User.InviteSettings",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "account" },
template: "Settings/Invites",
defaults: new { area = "User", controller = "User", action = "InviteSettings" }
);
routes.MapSubdomainRoute(
name: "User.BlogSettings",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "account" },
template: "Settings/Blog",
defaults: new { area = "User", controller = "User", action = "BlogSettings" }
);
routes.MapSubdomainRoute(
name: "User.UploadSettings",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "account" },
template: "Settings/Uploads",
defaults: new { area = "User", controller = "User", action = "UploadSettings" }
);
routes.MapSubdomainRoute(
name: "User.ResetPassword",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "account" },
template: "ResetPassword/{username?}",
defaults: new { area = "User", controller = "User", action = "ResetPassword" }
);
routes.MapSubdomainRoute(
name: "User.VerifyResetPassword",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "account" },
template: "SetPassword/{username}",
defaults: new { area = "User", controller = "User", action = "VerifyResetPassword" }
);
routes.MapSubdomainRoute(
name: "User.VerifyRecoveryEmail",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "account" },
template: "VerifyEmail/{username}",
defaults: new { area = "User", controller = "User", action = "VerifyRecoveryEmail" }
);
routes.MapSubdomainRoute(
name: "User.ViewServiceData",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "account" },
template: "ServiceData",
defaults: new { area = "User", controller = "User", action = "ViewServiceData" }
);
routes.MapSubdomainRoute(
name: "User.Action",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "account" },
template: "Action/{action}",
defaults: new { area = "User", controller = "User", action = "Index" }
);

routes.MapSubdomainRoute(
name: "User.ViewProfile",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "user" },
template: "{username?}",
defaults: new { area = "User", controller = "User", action = "ViewProfile" }
);
routes.MapSubdomainRoute(
name: "User.PGPKey",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "user" },
template: "{username}/PGP",
defaults: new { area = "User", controller = "User", action = "ViewRawPGP" }
);
}

public static void BuildVaultRoutes(this IRouteBuilder routes, Config config)
{
routes.MapSubdomainRoute(
name: "Vault.Index",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "vault", "v" },
template: "",
defaults: new { area = "Vault", controller = "Vault", action = "Index" }
);
routes.MapSubdomainRoute(
name: "Vault.NewVault",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "vault", "v" },
template: "Create",
defaults: new { area = "Vault", controller = "Vault", action = "NewVault" }
);
routes.MapSubdomainRoute(
name: "Vault.NewVaultFromService",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "vault", "v" },
template: "Create/{type}",
defaults: new { area = "Vault", controller = "Vault", action = "NewVaultFromService" }
);
routes.MapSubdomainRoute(
name: "Vault.EditVault",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "vault", "v" },
template: "Edit/{url}",
defaults: new { area = "Vault", controller = "Vault", action = "EditVault" }
);
routes.MapSubdomainRoute(
name: "Vault.Delete",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "vault", "v" },
template: "Delete",
defaults: new { area = "Vault", controller = "Vault", action = "Delete" }
);
routes.MapSubdomainRoute(
name: "Vault.ViewVault",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "vault", "v" },
template: "v/{id}",
defaults: new { area = "Vault", controller = "Vault", action = "ViewVault" }
);
routes.MapSubdomainRoute(
name: "Vault.Action",
domains: new List<string>() { config.Host },
subDomains: new List<string>() { "vault", "v" },
template: "Action/{action}",
defaults: new { area = "Vault", controller = "Vault", action = "Index" }
);
}
}
}

+ 32
- 40
Teknik/Startup.cs View File

@@ -1,56 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Teknik.Data;
using Teknik.Utilities;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Teknik.Logging;
using System.IO;
using Microsoft.Extensions.Logging;
using Teknik.Configuration;
using Teknik.Middleware;
using Microsoft.AspNetCore.ResponseCompression;
using System.IO.Compression;
using System.Text;
using Microsoft.AspNetCore.Authentication.Cookies;
using IdentityServer4.Models;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Teknik.Attributes;
using Teknik.Filters;
using Microsoft.Net.Http.Headers;
using Teknik.Areas.Users.Models;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.IdentityModel.Tokens;
using Microsoft.AspNetCore.Authentication;
using IdentityModel;
using Teknik.Security;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Authorization;
using System.Text.Encodings.Web;
using Microsoft.Extensions.Hosting;
using Teknik.Tracking;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Teknik.Logging;
using Teknik.Utilities.Routing;

namespace Teknik
{
public class Startup
{
public Startup(IHostingEnvironment env)
public Startup(IWebHostEnvironment env)
{
Environment = env;
}
public IHostingEnvironment Environment { get; }
public IWebHostEnvironment Environment { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
@@ -80,23 +66,26 @@ namespace Teknik

if (config.DevEnvironment)
{
Environment.EnvironmentName = EnvironmentName.Development;
Environment.EnvironmentName = Environments.Development;
}
else
{
Environment.EnvironmentName = EnvironmentName.Production;
Environment.EnvironmentName = Environments.Production;
}

services.AddHttpsRedirection(options =>
{
options.RedirectStatusCode = (Environment.IsDevelopment()) ? StatusCodes.Status307TemporaryRedirect : StatusCodes.Status308PermanentRedirect;
#if DEBUG
options.HttpsPort = 5050;
options.HttpsPort = 8050;
#else
options.HttpsPort = 443;
#endif
});

services.AddControllersWithViews()
.AddControllersAsServices();

services.AddHostedService<TrackingService>();
services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();

@@ -124,7 +113,6 @@ namespace Teknik
options.Cookie.Name = "TeknikWeb";
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
options.Cookie.Expiration = TimeSpan.FromDays(30);
options.ExpireTimeSpan = TimeSpan.FromDays(30);
});

@@ -154,9 +142,6 @@ namespace Teknik
options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
});

// Core MVC
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

services.AddTransient<CookieEventHandler>();

services.AddAuthentication(options =>
@@ -179,7 +164,6 @@ namespace Teknik
{
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
options.Cookie.Expiration = TimeSpan.FromDays(30);
options.ExpireTimeSpan = TimeSpan.FromDays(30);
options.Cookie.Name = "TeknikWebAuth";
options.Cookie.Domain = CookieHelper.GenerateCookieDomain(config.Host, false, Environment.IsDevelopment());
@@ -237,22 +221,26 @@ namespace Teknik
options.AddPolicy("FullAPI", p =>
{
p.AddAuthenticationSchemes("Bearer");
p.AddAuthenticationSchemes("AuthToken");
p.RequireScope("teknik-api.read");
p.RequireScope("teknik-api.write");
});
options.AddPolicy("ReadAPI", p =>
{
p.AddAuthenticationSchemes("Bearer");
p.AddAuthenticationSchemes("AuthToken");
p.RequireScope("teknik-api.read");
});
options.AddPolicy("WriteAPI", p =>
{
p.AddAuthenticationSchemes("Bearer");
p.AddAuthenticationSchemes("AuthToken");
p.RequireScope("teknik-api.write");
});
options.AddPolicy("AnyAPI", p =>
{
p.AddAuthenticationSchemes("Bearer");
p.AddAuthenticationSchemes("AuthToken");
p.RequireScope("teknik-api.read", "teknik-api.write");
});
});
@@ -270,6 +258,18 @@ namespace Teknik
// Create and Migrate the database
dbContext.Database.Migrate();

// Setup static files and cache them client side
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
ctx.Context.Response.Headers[HeaderNames.CacheControl] = "public,max-age=" + 31536000;
}
});

// Initiate Routing
app.UseRouting();

// Setup the HttpContext
app.UseHttpContextSetup();

@@ -307,25 +307,17 @@ namespace Teknik
app.UseCSP();
app.UseSecurityHeaders();

// Setup static files and cache them client side
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
ctx.Context.Response.Headers[HeaderNames.CacheControl] = "public,max-age=" + 31536000;
}
});

// Enable Cookie Policy
app.UseCookiePolicy();

// Authorize all the things!
app.UseAuthentication();
app.UseAuthorization();

// And finally, let's use MVC
app.UseMvc(routes =>
app.UseEndpoints(endpoints =>
{
routes.BuildRoutes(config);
endpoints.BuildEndpoints(config.Host, config.ShortenerConfig?.ShortenerHost);
});
}


+ 26
- 16
Teknik/Teknik.csproj View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<UserSecretsId>aspnet-TeknikCore-BE9563D1-0DFB-4141-903C-287B23FF22C7</UserSecretsId>
<RootNamespace>Teknik</RootNamespace>
<AssemblyName>Teknik</AssemblyName>
@@ -25,31 +25,35 @@
<None Remove="Areas\Home\Data\**" />
</ItemGroup>

<ItemGroup>
<Content Remove="App_Data\endpointMappings.json" />
</ItemGroup>

<ItemGroup>
<None Remove=".eslintrc" />
</ItemGroup>


<ItemGroup>
<PackageReference Include="IdentityServer4" Version="2.5.1" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.7.0" />
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="2.5.1" />
<PackageReference Include="IdentityServer4.EntityFramework" Version="2.5.1" />
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="1.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.2.6" PrivateAssets="all">
<PackageReference Include="IdentityServer4" Version="4.1.2" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="4.1.2" />
<PackageReference Include="IdentityServer4.EntityFramework" Version="4.1.2" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="5.0.2" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="5.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="5.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.7" PrivateAssets="all">
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
<PackageReference Include="Microsoft.SyndicationFeed.ReaderWriter" Version="1.0.2" />
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="2.2.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.3" PrivateAssets="All" />
<PackageReference Include="nClam" Version="4.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="QRCoder" Version="1.3.6" />
<PackageReference Include="TwoStepsAuthenticator" Version="1.3.2" />
<PackageReference Include="nClam" Version="5.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="QRCoder" Version="1.4.1" />
<PackageReference Include="TwoStepsAuthenticator" Version="1.4.1" />
</ItemGroup>

<ItemGroup>
@@ -79,6 +83,12 @@
<Folder Include="wwwroot\" />
</ItemGroup>

<ItemGroup>
<None Include="App_Data\endpointMappings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Configuration\Configuration.csproj" />
<ProjectReference Include="..\ContentScanningService\ContentScanningService.csproj" />

+ 1
- 1
Teknik/Views/Shared/_Footer.cshtml View File

@@ -29,7 +29,7 @@
<br />
<div class="row">
<div class="col-sm-5 col-sm-offset-1 text-left text-muted">
&copy; Teknik 2013-2020 | <a href="@Url.SubRouteUrl("faq", "FAQ.Index")">FAQ</a> | <a href="@Url.SubRouteUrl("privacy", "Privacy.Index")">Privacy</a> | <a href="@Url.SubRouteUrl("tos", "TOS.Index")">TOS</a> | <a href="@Url.SubRouteUrl("abuse", "Abuse.Index")">Abuse</a> | <a href="@Url.SubRouteUrl("stats", "Stats.Index")">Statistics</a>
&copy; Teknik 2013-2021 | <a href="@Url.SubRouteUrl("faq", "FAQ.Index")">FAQ</a> | <a href="@Url.SubRouteUrl("privacy", "Privacy.Index")">Privacy</a> | <a href="@Url.SubRouteUrl("tos", "TOS.Index")">TOS</a> | <a href="@Url.SubRouteUrl("abuse", "Abuse.Index")">Abuse</a> | <a href="@Url.SubRouteUrl("stats", "Stats.Index")">Statistics</a>
</div>
<div class="col-sm-5 text-right text-muted">
<div id="pagetime" style="display:none;">

+ 2
- 1
Teknik/_ViewImports.cshtml View File

@@ -3,9 +3,10 @@
@using Teknik.Configuration
@using Teknik.Utilities
@using Teknik.Utilities.TagHelpers
@using Teknik.Utilities.Routing
@using Microsoft.AspNetCore.Http.Extensions

@inject Microsoft.AspNetCore.Hosting.IHostingEnvironment HostingEnvironment
@inject Microsoft.AspNetCore.Hosting.IWebHostEnvironment HostingEnvironment
@inject Config Config

@addTagHelper "*, Microsoft.AspNetCore.Mvc.TagHelpers"

+ 3
- 3
Tracking/Tracking.csproj View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>Teknik.Tracking</AssemblyName>
<RootNamespace>Teknik.Tracking</RootNamespace>
<RuntimeIdentifiers>win-x86;win-x64;linux-x64;linux-arm;osx-x64</RuntimeIdentifiers>
@@ -13,8 +13,8 @@

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
</ItemGroup>

<ItemGroup>

+ 2
- 2
Utilities/BufferedFileStreamResult.cs View File

@@ -34,8 +34,8 @@ namespace Teknik.Utilities
{
if (!bufferOutput)
{
var bufferingFeature = context.HttpContext.Features.Get<IHttpBufferingFeature>();
bufferingFeature?.DisableResponseBuffering();
var bufferingFeature = context.HttpContext.Features.Get<IHttpResponseBodyFeature>();
bufferingFeature?.DisableBuffering();
}

return responseDelegate(context.HttpContext.Response);

+ 1
- 0
Utilities/Constants.cs View File

@@ -7,6 +7,7 @@ namespace Teknik.Utilities
public const string LOGO_PATH = "images/logo-black.svg";
public const string FAVICON_PATH = "images/favicon.ico";
public const string ROBOTS_PATH = "robots.txt";
public const string ENDPOINT_MAPPING_PATH = "endpointMappings.json";

public const string LOG_FILE_NAME_PREFIX = "Teknik";
public const string LOG_FILE_EXT = ".log";

+ 1
- 1
Utilities/FileHelper.cs View File

@@ -96,7 +96,7 @@ namespace Teknik.Utilities
return defaultExtension;
}

public static string MapPath(IHostingEnvironment env, string file)
public static string MapPath(IWebHostEnvironment env, string file)
{
var webRoot = env.WebRootPath;
return Path.Combine(webRoot, file);

+ 7
- 6
Utilities/IdentityClientScope.cs View File

@@ -1,29 +1,30 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Text;

namespace Teknik.Utilities
{
public enum IdentityClientScope
{
[DisplayName("openid")]
[Display(Name = "openid")]
[Description("The user identifier")]
[ReadOnly(true)]
openid,
[DisplayName("role")]
[Display(Name = "role")]
[Description("The user role")]
role,
[DisplayName("account-info")]
[Display(Name = "account-info")]
[Description("A user's account information")]
accountInfo,
[DisplayName("security-info")]
[Display(Name = "security-info")]
[Description("A user's security information")]
securityInfo,
[DisplayName("teknik-api.read")]
[Display(Name = "teknik-api.read")]
[Description("Read access to the Teknik API")]
teknikApiRead,
[DisplayName("teknik-api.write")]
[Display(Name = "teknik-api.write")]
[Description("Write access to the Teknik API")]
teknikApiWrite,
}

+ 100
- 0
Utilities/Routing/EndpointHelper.cs View File

@@ -0,0 +1,100 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Linq;

namespace Teknik.Utilities.Routing
{
public static class EndpointHelper
{
public static void BuildEndpoints(this IEndpointRouteBuilder endpoints, string fullHost, string shortHost)
{
// Get the endpoint mappings
var mappings = GetEndpointMappings();

// Create a subdomain endpoint for each mapping
foreach (var mapping in mappings)
{
var domains = GetDomainsFromHostTypes(fullHost, shortHost, mapping.HostTypes);

var defaultObj = new ExpandoObject();
if (mapping.Defaults != null)
{
var defaults = mapping.Defaults as JObject;
foreach (var defaultVal in defaults)
{
defaultObj.TryAdd(defaultVal.Key, defaultVal.Value);
}
}
defaultObj.TryAdd("area", mapping.Area);

endpoints.MapSubdomainEndpoint(
name: mapping.Name,
domains: domains,
subDomains: mapping.SubDomains,
pattern: mapping.Pattern,
area: mapping.Area,
defaults: defaultObj,
adjustPattern: mapping.AdjustPattern ?? true
);
}
}

public static EndpointMapping GetEndpointMapping(string name)
{
var mappings = GetEndpointMappings();
return mappings.FirstOrDefault(m => m.Name == name);
}

public static List<EndpointMapping> GetEndpointMappings()
{
string dataDir = (string)AppDomain.CurrentDomain.GetData("DataDirectory");
string file = Path.Combine(dataDir, Constants.ENDPOINT_MAPPING_PATH);
if (File.Exists(file))
{
JsonSerializer serializer = new JsonSerializer();
using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
using (var sr = new StreamReader(fs))
using (var jsonTextReader = new JsonTextReader(sr))
{
return (List<EndpointMapping>)serializer.Deserialize(jsonTextReader, typeof(List<EndpointMapping>));
}
}
return new List<EndpointMapping>();
}

private static List<string> GetDomainsFromHostTypes(string fullHost, string shortHost, List<HostType> hostTypes)
{
var domains = new List<string>();

if (hostTypes != null)
{
foreach (var hostType in hostTypes)
{
switch (hostType)
{
case HostType.Full:
if (!string.IsNullOrEmpty(fullHost) &&
!domains.Contains(fullHost))
domains.Add(fullHost);
break;
case HostType.Short:
if (!string.IsNullOrEmpty(shortHost) &&
!domains.Contains(shortHost))
domains.Add(shortHost);
break;
}
}
}

return domains;
}
}
}

+ 18
- 0
Utilities/Routing/EndpointMapping.cs View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Teknik.Utilities.Routing
{
public class EndpointMapping
{
public string Name { get; set; }
public string Area { get; set; }
public string Pattern { get; set; }
public bool? AdjustPattern { get; set; }
public List<HostType> HostTypes { get; set; }
public List<string> SubDomains { get; set; }
public object Defaults { get; set; }
}
}

+ 13