From f6fbb4c8629bad60dc7c313ff2f9a7ad7e2ff49f Mon Sep 17 00:00:00 2001 From: Stanley Dimant Date: Fri, 17 Jun 2022 23:49:08 +0200 Subject: [PATCH] yeah idk, basic form of reg, auth, upload, whitelist. lots of stuff. --- .../MareSynchronos.API.csproj | 7 + .../MareSynchronos.API/WhitelistDto.cs | 10 ++ MareSynchronosServer/MareSynchronosServer.sln | 31 ++++ .../Authentication/IdBasedUserIdProvider.cs | 14 ++ .../SecretKeyAuthenticationHandler.cs | 58 +++++++ .../Data/MareDbContext.cs | 23 +++ .../MareSynchronosServer/Hubs/Connection.cs | 21 +++ .../MareSynchronosServer/Hubs/Files.cs | 75 +++++++++ .../MareSynchronosServer/Hubs/User.cs | 157 ++++++++++++++++++ .../MareSynchronosServer.csproj | 26 +++ .../MareSynchronosServer/Models/FileCache.cs | 17 ++ .../MareSynchronosServer/Models/User.cs | 15 ++ .../MareSynchronosServer/Models/Whitelist.cs | 14 ++ .../MareSynchronosServer/Program.cs | 39 +++++ .../Properties/launchSettings.json | 21 +++ .../Properties/serviceDependencies.json | 13 ++ .../Properties/serviceDependencies.local.json | 16 ++ .../MareSynchronosServer/Startup.cs | 93 +++++++++++ .../appsettings.Development.json | 10 ++ .../MareSynchronosServer/appsettings.json | 13 ++ 20 files changed, 673 insertions(+) create mode 100644 MareSynchronosServer/MareSynchronos.API/MareSynchronos.API.csproj create mode 100644 MareSynchronosServer/MareSynchronos.API/WhitelistDto.cs create mode 100644 MareSynchronosServer/MareSynchronosServer.sln create mode 100644 MareSynchronosServer/MareSynchronosServer/Authentication/IdBasedUserIdProvider.cs create mode 100644 MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyAuthenticationHandler.cs create mode 100644 MareSynchronosServer/MareSynchronosServer/Data/MareDbContext.cs create mode 100644 MareSynchronosServer/MareSynchronosServer/Hubs/Connection.cs create mode 100644 MareSynchronosServer/MareSynchronosServer/Hubs/Files.cs create mode 100644 MareSynchronosServer/MareSynchronosServer/Hubs/User.cs create mode 100644 MareSynchronosServer/MareSynchronosServer/MareSynchronosServer.csproj create mode 100644 MareSynchronosServer/MareSynchronosServer/Models/FileCache.cs create mode 100644 MareSynchronosServer/MareSynchronosServer/Models/User.cs create mode 100644 MareSynchronosServer/MareSynchronosServer/Models/Whitelist.cs create mode 100644 MareSynchronosServer/MareSynchronosServer/Program.cs create mode 100644 MareSynchronosServer/MareSynchronosServer/Properties/launchSettings.json create mode 100644 MareSynchronosServer/MareSynchronosServer/Properties/serviceDependencies.json create mode 100644 MareSynchronosServer/MareSynchronosServer/Properties/serviceDependencies.local.json create mode 100644 MareSynchronosServer/MareSynchronosServer/Startup.cs create mode 100644 MareSynchronosServer/MareSynchronosServer/appsettings.Development.json create mode 100644 MareSynchronosServer/MareSynchronosServer/appsettings.json diff --git a/MareSynchronosServer/MareSynchronos.API/MareSynchronos.API.csproj b/MareSynchronosServer/MareSynchronos.API/MareSynchronos.API.csproj new file mode 100644 index 0000000..f208d30 --- /dev/null +++ b/MareSynchronosServer/MareSynchronos.API/MareSynchronos.API.csproj @@ -0,0 +1,7 @@ + + + + net5.0 + + + diff --git a/MareSynchronosServer/MareSynchronos.API/WhitelistDto.cs b/MareSynchronosServer/MareSynchronos.API/WhitelistDto.cs new file mode 100644 index 0000000..a46a9db --- /dev/null +++ b/MareSynchronosServer/MareSynchronos.API/WhitelistDto.cs @@ -0,0 +1,10 @@ +namespace MareSynchronos.API +{ + public class WhitelistDto + { + public string OtherUID { get; set; } + public bool IsPaused { get; set; } + public bool IsSynced { get; set; } + public bool IsPausedFromOthers { get; set; } + } +} \ No newline at end of file diff --git a/MareSynchronosServer/MareSynchronosServer.sln b/MareSynchronosServer/MareSynchronosServer.sln new file mode 100644 index 0000000..c345141 --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.2.32602.215 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MareSynchronosServer", "MareSynchronosServer\MareSynchronosServer.csproj", "{029CA97F-E0BA-4172-A191-EA21FB61AD0F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MareSynchronos.API", "MareSynchronos.API\MareSynchronos.API.csproj", "{E1D8937E-26D0-46FF-8EDA-F35BF8AEFF1D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {029CA97F-E0BA-4172-A191-EA21FB61AD0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {029CA97F-E0BA-4172-A191-EA21FB61AD0F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {029CA97F-E0BA-4172-A191-EA21FB61AD0F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {029CA97F-E0BA-4172-A191-EA21FB61AD0F}.Release|Any CPU.Build.0 = Release|Any CPU + {E1D8937E-26D0-46FF-8EDA-F35BF8AEFF1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E1D8937E-26D0-46FF-8EDA-F35BF8AEFF1D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E1D8937E-26D0-46FF-8EDA-F35BF8AEFF1D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E1D8937E-26D0-46FF-8EDA-F35BF8AEFF1D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {78C476A5-6E88-449B-828D-A2465D9D3295} + EndGlobalSection +EndGlobal diff --git a/MareSynchronosServer/MareSynchronosServer/Authentication/IdBasedUserIdProvider.cs b/MareSynchronosServer/MareSynchronosServer/Authentication/IdBasedUserIdProvider.cs new file mode 100644 index 0000000..05aef38 --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/Authentication/IdBasedUserIdProvider.cs @@ -0,0 +1,14 @@ +using System.Linq; +using System.Security.Claims; +using Microsoft.AspNetCore.SignalR; + +namespace MareSynchronosServer.Authentication +{ + public class IdBasedUserIdProvider : IUserIdProvider + { + public string GetUserId(HubConnectionContext context) + { + return context.User!.Claims.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value; + } + } +} diff --git a/MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyAuthenticationHandler.cs b/MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyAuthenticationHandler.cs new file mode 100644 index 0000000..98210be --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyAuthenticationHandler.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Security.Cryptography; +using System.Text; +using System.Text.Encodings.Web; +using System.Threading.Tasks; +using MareSynchronosServer.Data; +using Microsoft.AspNetCore.Authentication; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Tokens; + +namespace MareSynchronosServer.Authentication +{ + public class SecretKeyAuthenticationHandler : AuthenticationHandler + { + private readonly MareDbContext _mareDbContext; + public const string AUTH_SCHEME = "SecretKeyAuth"; + + protected override Task HandleAuthenticateAsync() + { + if (!Request.Headers.ContainsKey("Authorization")) + return Task.FromResult(AuthenticateResult.Fail("Failed Authorization")); + + var authHeader = Request.Headers["Authorization"].ToString(); + + if (string.IsNullOrEmpty(authHeader)) + return Task.FromResult(AuthenticateResult.Fail("Failed Authorization")); + + using var sha256 = SHA256.Create(); + var hashedHeader = BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(authHeader))).Replace("-", ""); + var user = _mareDbContext.Users.SingleOrDefault(m => m.SecretKey == hashedHeader); + + if (user == null) + { + return Task.FromResult(AuthenticateResult.Fail("Failed Authorization")); + } + + var claims = new List { + new Claim(ClaimTypes.Name, user.CharacterIdentification ?? "Unknown"), + new Claim(ClaimTypes.NameIdentifier, user.UID) + }; + + var identity = new ClaimsIdentity(claims, nameof(SecretKeyAuthenticationHandler)); + var principal = new ClaimsPrincipal(identity); + var ticket = new AuthenticationTicket(principal, this.Scheme.Name); + + return Task.FromResult(AuthenticateResult.Success(ticket)); + } + + public SecretKeyAuthenticationHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, MareDbContext mareDbContext) : base(options, logger, encoder, clock) + { + _mareDbContext = mareDbContext; + } + } +} diff --git a/MareSynchronosServer/MareSynchronosServer/Data/MareDbContext.cs b/MareSynchronosServer/MareSynchronosServer/Data/MareDbContext.cs new file mode 100644 index 0000000..ad00f9d --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/Data/MareDbContext.cs @@ -0,0 +1,23 @@ +using MareSynchronosServer.Models; +using Microsoft.EntityFrameworkCore; + +namespace MareSynchronosServer.Data +{ + public class MareDbContext : Microsoft.EntityFrameworkCore.DbContext + { + public MareDbContext(DbContextOptions options) : base(options) + { + } + + public DbSet Users { get; set; } + public DbSet Files { get; set; } + public DbSet Whitelists { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity().ToTable("Users"); + modelBuilder.Entity().ToTable("FileCaches"); + modelBuilder.Entity().ToTable("Whitelists"); + } + } +} diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/Connection.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/Connection.cs new file mode 100644 index 0000000..745b51a --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/Connection.cs @@ -0,0 +1,21 @@ +using System.Diagnostics; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNetCore.SignalR; + +namespace MareSynchronosServer.Hubs +{ + public class Connection : Hub + { + public string Heartbeat() + { + var userId = Context.User!.Claims.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value; + if (userId != null) + { + var user = Clients.User(userId); + } + return userId ?? string.Empty; + } + } +} diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/Files.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/Files.cs new file mode 100644 index 0000000..d84b5e1 --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/Files.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Security.Claims; +using System.Security.Cryptography; +using System.Threading.Tasks; +using MareSynchronosServer.Authentication; +using MareSynchronosServer.Data; +using MareSynchronosServer.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.SignalR; + +namespace MareSynchronosServer.Hubs +{ + [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)] + public class Files : Hub + { + private readonly MareDbContext _dbContext; + + public Files(MareDbContext dbContext) + { + _dbContext = dbContext; + } + + [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)] + public async Task SendFiles(List fileList) + { + var existingFiles = _dbContext.Files.Where(f => fileList.Contains(f.Hash)).ToList(); + foreach (var file in fileList.Where(f => existingFiles.All(e => e.Hash != f))) + { + var userId = Context.User!.Claims.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value ?? "Unknown"; + await _dbContext.Files.AddAsync(new FileCache() + { + Hash = file, + LastAccessTime = DateTime.Now, + Uploaded = false, + Uploader = _dbContext.Users.Single(u => u.UID == userId) + }); + await _dbContext.SaveChangesAsync(); + await Clients.Caller!.SendAsync("FileRequest", file); + } + } + + [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)] + public async Task UploadFile(string hash, byte[] file) + { + var relatedFile = _dbContext.Files.SingleOrDefault(f => f.Hash == hash); + if (relatedFile == null) return false; + var decodedFile = LZ4.LZ4Codec.Unwrap(file); + using var sha1 = new SHA1CryptoServiceProvider(); + var computedHash = await sha1.ComputeHashAsync(new MemoryStream(decodedFile)); + var computedHashString = BitConverter.ToString(computedHash).Replace("-", ""); + if (hash != computedHashString) + { + return false; + } + await File.WriteAllBytesAsync(@"G:\ServerTest\" + hash, file); + relatedFile.Uploaded = true; + relatedFile.LastAccessTime = DateTime.Now; + await _dbContext.SaveChangesAsync(); + return true; + } + + public override Task OnDisconnectedAsync(Exception exception) + { + var userId = Context.User!.Claims.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value; + var notUploadedFiles = _dbContext.Files.Where(f => !f.Uploaded && f.Uploader.UID == userId).ToList(); + _dbContext.RemoveRange(notUploadedFiles); + _dbContext.SaveChanges(); + return base.OnDisconnectedAsync(exception); + } + } +} diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/User.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/User.cs new file mode 100644 index 0000000..48f762e --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/User.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Security.Claims; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; +using MareSynchronos.API; +using MareSynchronosServer.Authentication; +using MareSynchronosServer.Data; +using MareSynchronosServer.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.SignalR; +using Microsoft.EntityFrameworkCore; + +namespace MareSynchronosServer.Hubs +{ + public class User : Hub + { + private readonly MareDbContext _dbContext; + + public User(MareDbContext dbContext) + { + _dbContext = dbContext; + } + + public async Task Register() + { + using var sha256 = SHA256.Create(); + var computedHash = BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(GenerateRandomString(64)))).Replace("-", ""); + var user = new Models.User + { + SecretKey = BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(computedHash))) + .Replace("-", ""), + }; + + var hasValidUid = false; + while (!hasValidUid) + { + var uid = GenerateRandomString(10); + if (_dbContext.Users.Any(u => u.UID == uid)) continue; + user.UID = uid; + hasValidUid = true; + } + _dbContext.Users.Add(user); + + await _dbContext.SaveChangesAsync(); + return computedHash; + } + + [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)] + public string GetUID() + { + return Context.User!.Claims.Single(c => c.Type == ClaimTypes.NameIdentifier).Value; + } + + [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)] + public async Task SendWhitelist(List whiteListEntries) + { + var currentUserId = Context.User!.Claims.Single(c => c.Type == ClaimTypes.NameIdentifier).Value; + var user = _dbContext.Users.Single(u => u.UID == currentUserId); + var userWhitelists = _dbContext.Whitelists + .Include(w => w.User) + .Include(w => w.OtherUser) + .Where(w => w.User.UID == currentUserId) + .ToList(); + foreach (var whitelist in whiteListEntries) + { + var otherEntry = _dbContext.Whitelists.SingleOrDefault(w => + w.User.UID == whitelist.OtherUID && w.OtherUser.UID == user.UID); + + var prevEntry = userWhitelists.SingleOrDefault(w => w.OtherUser.UID == whitelist.OtherUID); + if (prevEntry != null) + { + prevEntry.IsPaused = whitelist.IsPaused; + } + else + { + var otherUser = _dbContext.Users.SingleOrDefault(u => u.UID == whitelist.OtherUID); + if (otherUser != null) + { + Whitelist wl = new Whitelist + { + User = user, + OtherUser = otherUser, + IsPaused = whitelist.IsPaused + }; + otherEntry = wl; + await _dbContext.Whitelists.AddAsync(wl); + } + } + + if (otherEntry != null) + { + await Clients.User(whitelist.OtherUID).SendAsync("UpdateWhitelist", currentUserId, true, + whitelist.IsPaused); + } + + await _dbContext.SaveChangesAsync(); + } + + foreach (var deletedEntry in userWhitelists.Where(u => whiteListEntries.All(e => e.OtherUID != u.OtherUser.UID)).ToList()) + { + var otherEntry = _dbContext.Whitelists.SingleOrDefault(w => + w.User.UID == deletedEntry.OtherUser.UID && w.OtherUser.UID == user.UID); + if (otherEntry != null) + { + await Clients.User(otherEntry.User.UID).SendAsync("UpdateWhitelist", currentUserId, false, false); + } + + _dbContext.Whitelists.Remove(deletedEntry); + } + _dbContext.Whitelists.RemoveRange(); + await _dbContext.SaveChangesAsync(); + } + + [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)] + public async Task> GetWhitelist() + { + string userid = Context.User!.Claims.Single(c => c.Type == ClaimTypes.NameIdentifier).Value; + return _dbContext.Whitelists.Include(u => u.OtherUser).Include(u => u.User).Where(w => w.User.UID == userid) + .ToList() + .Select(w => + { + var otherEntry = _dbContext.Whitelists.SingleOrDefault(a => a.User.UID == w.OtherUser.UID && a.OtherUser.UID == userid); + return new WhitelistDto + { + IsPaused = w.IsPaused, + OtherUID = w.OtherUser.UID, + IsSynced = otherEntry != null, + IsPausedFromOthers = otherEntry?.IsPaused ?? false + }; + }).ToList(); + } + + public static string GenerateRandomString(int length, string allowableChars = null) + { + if (string.IsNullOrEmpty(allowableChars)) + allowableChars = @"ABCDEFGHJKLMNPQRSTUVWXYZ0123456789"; + + // Generate random data + var rnd = new byte[length]; + using (var rng = new RNGCryptoServiceProvider()) + rng.GetBytes(rnd); + + // Generate the output string + var allowable = allowableChars.ToCharArray(); + var l = allowable.Length; + var chars = new char[length]; + for (var i = 0; i < length; i++) + chars[i] = allowable[rnd[i] % l]; + + return new string(chars); + } + } +} diff --git a/MareSynchronosServer/MareSynchronosServer/MareSynchronosServer.csproj b/MareSynchronosServer/MareSynchronosServer/MareSynchronosServer.csproj new file mode 100644 index 0000000..ebb579b --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/MareSynchronosServer.csproj @@ -0,0 +1,26 @@ + + + + net5.0 + aspnet-MareSynchronosServer-BA82A12A-0B30-463C-801D-B7E81318CD50 + + + + + + + + + + + + + + + + + + + + + diff --git a/MareSynchronosServer/MareSynchronosServer/Models/FileCache.cs b/MareSynchronosServer/MareSynchronosServer/Models/FileCache.cs new file mode 100644 index 0000000..95c3297 --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/Models/FileCache.cs @@ -0,0 +1,17 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace MareSynchronosServer.Models +{ + public class FileCache + { + [Key] + public string Hash { get; set; } + public User Uploader { get; set; } + public bool Uploaded { get; set; } + public DateTime LastAccessTime { get; set; } + [Timestamp] + public byte[] Timestamp { get; set; } + } +} diff --git a/MareSynchronosServer/MareSynchronosServer/Models/User.cs b/MareSynchronosServer/MareSynchronosServer/Models/User.cs new file mode 100644 index 0000000..af22949 --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/Models/User.cs @@ -0,0 +1,15 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace MareSynchronosServer.Models +{ + public class User + { + [Key] + public string UID { get; set; } + public string SecretKey { get; set; } + public string CharacterIdentification { get; set; } + [Timestamp] + public byte[] Timestamp { get; set; } + } +} diff --git a/MareSynchronosServer/MareSynchronosServer/Models/Whitelist.cs b/MareSynchronosServer/MareSynchronosServer/Models/Whitelist.cs new file mode 100644 index 0000000..fc1290f --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/Models/Whitelist.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; + +namespace MareSynchronosServer.Models +{ + public class Whitelist + { + public int Id { get; set; } + public User User { get; set; } + public User OtherUser { get; set; } + public bool IsPaused { get; set; } + [Timestamp] + public byte[] Timestamp { get; set; } + } +} diff --git a/MareSynchronosServer/MareSynchronosServer/Program.cs b/MareSynchronosServer/MareSynchronosServer/Program.cs new file mode 100644 index 0000000..b69fe88 --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/Program.cs @@ -0,0 +1,39 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using MareSynchronosServer.Data; +using Microsoft.Extensions.DependencyInjection; + +namespace MareSynchronosServer +{ + public class Program + { + public static void Main(string[] args) + { + var host = CreateHostBuilder(args).Build(); + + using (var scope = host.Services.CreateScope()) + { + var services = scope.ServiceProvider; + var context = services.GetRequiredService(); + context.Database.EnsureCreated(); + } + + host.Run(); + } + + // Server=localhost\SQLEXPRESS;Database=master;Trusted_Connection=True; + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } +} diff --git a/MareSynchronosServer/MareSynchronosServer/Properties/launchSettings.json b/MareSynchronosServer/MareSynchronosServer/Properties/launchSettings.json new file mode 100644 index 0000000..f9f59b7 --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/Properties/launchSettings.json @@ -0,0 +1,21 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:43136", + "sslPort": 44364 + } + }, + "profiles": { + "MareSynchronosServer": { + "commandName": "Project", + "dotnetRunMessages": "true", + "launchBrowser": false, + "applicationUrl": "https://localhost:5001;http://localhost:5000;https://darkarchon.internet-box.ch:5001;http://darkarchon.internet-box.ch:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/MareSynchronosServer/MareSynchronosServer/Properties/serviceDependencies.json b/MareSynchronosServer/MareSynchronosServer/Properties/serviceDependencies.json new file mode 100644 index 0000000..7d43f21 --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/Properties/serviceDependencies.json @@ -0,0 +1,13 @@ +{ + "dependencies": { + "mssql1": { + "type": "mssql", + "connectionId": "ConnectionStrings:DefaultConnection", + "dynamicId": null + }, + "secrets1": { + "type": "secrets", + "connectionId": null + } + } +} \ No newline at end of file diff --git a/MareSynchronosServer/MareSynchronosServer/Properties/serviceDependencies.local.json b/MareSynchronosServer/MareSynchronosServer/Properties/serviceDependencies.local.json new file mode 100644 index 0000000..7aa7fcd --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/Properties/serviceDependencies.local.json @@ -0,0 +1,16 @@ +{ + "dependencies": { + "mssql1": { + "secretStore": "LocalSecretsFile", + "type": "mssql.onprem", + "connectionId": "ConnectionStrings:DefaultConnection", + "dynamicId": null + }, + "secrets1": { + "secretStore": null, + "resourceId": null, + "type": "secrets.user", + "connectionId": null + } + } +} \ No newline at end of file diff --git a/MareSynchronosServer/MareSynchronosServer/Startup.cs b/MareSynchronosServer/MareSynchronosServer/Startup.cs new file mode 100644 index 0000000..2c73d6f --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/Startup.cs @@ -0,0 +1,93 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.HttpsPolicy; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Identity.UI; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Bazinga.AspNetCore.Authentication.Basic; +using MareSynchronosServer.Authentication; +using MareSynchronosServer.Data; +using MareSynchronosServer.Hubs; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.ResponseCompression; +using Microsoft.AspNetCore.SignalR; + +namespace MareSynchronosServer +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + + // This method gets called by the runtime. Use this method to add services to the container. + // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 + public void ConfigureServices(IServiceCollection services) + { + services.AddSignalR(hubOptions => + { + hubOptions.MaximumReceiveMessageSize = long.MaxValue; + }); + services.AddSingleton(); + + services.AddResponseCompression(opts => + { + opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[] { "application/octet-stream" }); + }); + services.AddDbContext(options => + options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); + services.AddDatabaseDeveloperPageExceptionFilter(); + services.AddAuthentication(options => options.DefaultScheme = SecretKeyAuthenticationHandler.AUTH_SCHEME) + .AddScheme(SecretKeyAuthenticationHandler.AUTH_SCHEME, options => { }); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + app.UseMigrationsEndPoint(); + } + else + { + app.UseExceptionHandler("/Error"); + // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + app.UseHsts(); + } + + app.UseHttpsRedirection(); + app.UseStaticFiles(); + + app.UseRouting(); + + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapHub("/heartbeat"); + endpoints.MapHub("/user"); + endpoints.MapHub("/files", options => + { + options.ApplicationMaxBufferSize = long.MaxValue; + options.TransportMaxBufferSize = long.MaxValue; + }); + }); + } + } +} diff --git a/MareSynchronosServer/MareSynchronosServer/appsettings.Development.json b/MareSynchronosServer/MareSynchronosServer/appsettings.Development.json new file mode 100644 index 0000000..5173757 --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/appsettings.Development.json @@ -0,0 +1,10 @@ +{ + "DetailedErrors": true, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/MareSynchronosServer/MareSynchronosServer/appsettings.json b/MareSynchronosServer/MareSynchronosServer/appsettings.json new file mode 100644 index 0000000..711b9b4 --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/appsettings.json @@ -0,0 +1,13 @@ +{ + "ConnectionStrings": { + "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-MareSynchronosServer-BA82A12A-0B30-463C-801D-B7E81318CD50;Trusted_Connection=True;MultipleActiveResultSets=true" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +}