add logging stuff

This commit is contained in:
Stanley Dimant
2022-07-03 02:24:32 +02:00
parent d56923d553
commit 15b220dc8b
9 changed files with 81 additions and 49 deletions

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Security.Claims; using System.Security.Claims;
@@ -16,6 +17,7 @@ namespace MareSynchronosServer.Authentication
{ {
public class SecretKeyAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions> public class SecretKeyAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{ {
public static ConcurrentDictionary<string, object> IdentificationLocks = new();
private readonly MareDbContext _mareDbContext; private readonly MareDbContext _mareDbContext;
public const string AuthScheme = "SecretKeyAuth"; public const string AuthScheme = "SecretKeyAuth";
@@ -45,15 +47,26 @@ namespace MareSynchronosServer.Authentication
return AuthenticateResult.Fail("Failed Authorization"); return AuthenticateResult.Fail("Failed Authorization");
} }
if (!IdentificationLocks.TryGetValue(charNameHeader, out var lockObject))
{
lockObject = new();
IdentificationLocks[charNameHeader] = lockObject;
}
if (user.CharacterIdentification != charNameHeader) if (user.CharacterIdentification != charNameHeader)
{
lock (lockObject)
{ {
try try
{ {
user.CharacterIdentification = charNameHeader; user.CharacterIdentification = charNameHeader;
_mareDbContext.Users.Update(user); _mareDbContext.Users.Update(user);
await _mareDbContext.SaveChangesAsync(); _mareDbContext.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
}
} }
catch (DbUpdateConcurrencyException) { }
} }
var claims = new List<Claim> { var claims = new List<Claim> {

View File

@@ -44,12 +44,13 @@ namespace MareSynchronosServer
_logger.LogInformation($"Cleaning up files older than {filesOlderThanDays} days"); _logger.LogInformation($"Cleaning up files older than {filesOlderThanDays} days");
using var scope = _services.CreateScope(); using var scope = _services.CreateScope();
var dbContext = scope.ServiceProvider.GetService<MareDbContext>(); var dbContext = scope.ServiceProvider.GetService<MareDbContext>()!;
var prevTime = DateTime.Now.Subtract(TimeSpan.FromDays(filesOlderThanDays)); var prevTime = DateTime.Now.Subtract(TimeSpan.FromDays(filesOlderThanDays));
var filesToDelete = var filesToDelete =
dbContext.Files.Where(f => f.LastAccessTime < prevTime); dbContext.Files.Where(f => f.LastAccessTime < prevTime);
dbContext.RemoveRange(filesToDelete); dbContext.RemoveRange(filesToDelete);
dbContext.SaveChanges();
foreach (var file in filesToDelete) foreach (var file in filesToDelete)
{ {
var fileName = Path.Combine(_configuration["CacheDirectory"], file.Hash); var fileName = Path.Combine(_configuration["CacheDirectory"], file.Hash);
@@ -59,9 +60,6 @@ namespace MareSynchronosServer
File.Delete(fileName); File.Delete(fileName);
} }
} }
dbContext.SaveChanges();
var allFiles = dbContext.Files; var allFiles = dbContext.Files;
foreach (var file in allFiles) foreach (var file in allFiles)
{ {

View File

@@ -21,7 +21,7 @@ namespace MareSynchronosServer.Hubs
if (userId != null) if (userId != null)
{ {
Logger.LogInformation("Heartbeat from " + userId); Logger.LogInformation("Connection from " + userId);
var user = (await DbContext.Users.SingleAsync(u => u.UID == userId)); var user = (await DbContext.Users.SingleAsync(u => u.UID == userId));
return new LoggedInUserDto return new LoggedInUserDto
{ {

View File

@@ -42,6 +42,7 @@ namespace MareSynchronosServer.Hubs
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)] [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
public async Task<List<UploadFileDto>> SendFiles(List<string> fileListHashes) public async Task<List<UploadFileDto>> SendFiles(List<string> fileListHashes)
{ {
fileListHashes = fileListHashes.Distinct().ToList();
Logger.LogInformation("User " + AuthenticatedUserId + " sending files"); Logger.LogInformation("User " + AuthenticatedUserId + " sending files");
var forbiddenFiles = DbContext.ForbiddenUploadEntries.Where(f => fileListHashes.Contains(f.Hash)); var forbiddenFiles = DbContext.ForbiddenUploadEntries.Where(f => fileListHashes.Contains(f.Hash));
var filesToUpload = new List<UploadFileDto>(); var filesToUpload = new List<UploadFileDto>();
@@ -51,10 +52,11 @@ namespace MareSynchronosServer.Hubs
Hash = f.Hash, Hash = f.Hash,
IsForbidden = true IsForbidden = true
})); }));
var existingFiles = DbContext.Files.Where(f => fileListHashes.Contains(f.Hash)).ToList(); fileListHashes.RemoveAll(f => filesToUpload.Any(u => u.Hash == f));
var existingFiles = DbContext.Files.Where(f => fileListHashes.Contains(f.Hash));
foreach (var file in fileListHashes.Where(f => existingFiles.All(e => e.Hash != f) && filesToUpload.All(u => u.Hash != f))) foreach (var file in fileListHashes.Where(f => existingFiles.All(e => e.Hash != f) && filesToUpload.All(u => u.Hash != f)))
{ {
Logger.LogInformation("Needs upload: " + file); Logger.LogInformation("User " + AuthenticatedUserId + " needs upload: " + file);
var userId = AuthenticatedUserId; var userId = AuthenticatedUserId;
await DbContext.Files.AddAsync(new FileCache() await DbContext.Files.AddAsync(new FileCache()
{ {
@@ -90,10 +92,27 @@ namespace MareSynchronosServer.Hubs
var forbiddenFile = DbContext.ForbiddenUploadEntries.SingleOrDefault(f => f.Hash == hash); var forbiddenFile = DbContext.ForbiddenUploadEntries.SingleOrDefault(f => f.Hash == hash);
if (forbiddenFile != null) return; if (forbiddenFile != null) return;
var uploadedFile = new List<byte>(); var uploadedFile = new List<byte>();
try
{
await foreach (var chunk in fileContent) await foreach (var chunk in fileContent)
{ {
uploadedFile.AddRange(chunk); uploadedFile.AddRange(chunk);
} }
}
catch
{
DbContext.Files.Remove(relatedFile);
try
{
await DbContext.SaveChangesAsync();
}
catch
{
// already removed
}
return;
}
Logger.LogInformation("User " + AuthenticatedUserId + " upload finished: " + hash + ", size: " + uploadedFile.Count); Logger.LogInformation("User " + AuthenticatedUserId + " upload finished: " + hash + ", size: " + uploadedFile.Count);
@@ -115,6 +134,7 @@ namespace MareSynchronosServer.Hubs
relatedFile.Uploaded = true; relatedFile.Uploaded = true;
relatedFile.LastAccessTime = DateTime.Now; relatedFile.LastAccessTime = DateTime.Now;
await DbContext.SaveChangesAsync(); await DbContext.SaveChangesAsync();
Logger.LogInformation("File " + hash + " added to DB");
return; return;
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -69,37 +69,11 @@ namespace MareSynchronosServer.Hubs
return AuthenticatedUserId; return AuthenticatedUserId;
} }
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
public async Task GetCharacterData(Dictionary<string, int> visibleCharacterWithJobs)
{
var uid = AuthenticatedUserId;
Dictionary<string, CharacterCacheDto> ret = new();
var entriesHavingThisUser = DbContext.ClientPairs
.Include(w => w.User)
.Include(w => w.OtherUser)
.Where(w => w.OtherUser.UID == uid && !w.IsPaused && visibleCharacterWithJobs.Keys.Contains(w.User.CharacterIdentification))
.ToList();
foreach (var pair in entriesHavingThisUser)
{
bool isNotPaused = await DbContext.ClientPairs.AnyAsync(w =>
!w.IsPaused && w.User.UID == uid && w.OtherUser.UID == pair.User.UID);
if (!isNotPaused) continue;
var dictEntry = visibleCharacterWithJobs[pair.User.CharacterIdentification];
var cachedChar = await
DbContext.CharacterData.SingleOrDefaultAsync(c => c.UserId == pair.User.UID && c.JobId == dictEntry);
if (cachedChar != null)
{
await Clients.User(uid).SendAsync("ReceiveCharacterData", cachedChar.CharacterCache,
pair.User.CharacterIdentification);
}
}
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)] [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
public async Task PushCharacterDataToVisibleClients(CharacterCacheDto characterCache, List<string> visibleCharacterIds) public async Task PushCharacterDataToVisibleClients(CharacterCacheDto characterCache, List<string> visibleCharacterIds)
{ {
Logger.LogInformation("User " + AuthenticatedUserId + " pushing character data to visible clients"); Logger.LogInformation("User " + AuthenticatedUserId + " pushing character data to " + visibleCharacterIds.Count + " visible clients");
var uid = AuthenticatedUserId; var uid = AuthenticatedUserId;
var entriesHavingThisUser = DbContext.ClientPairs var entriesHavingThisUser = DbContext.ClientPairs
@@ -166,7 +140,7 @@ namespace MareSynchronosServer.Hubs
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)] [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
public async Task<List<string>> GetOnlineCharacters() public async Task<List<string>> GetOnlineCharacters()
{ {
Logger.LogInformation("User " + AuthenticatedUserId + " sent character hash"); Logger.LogInformation("User " + AuthenticatedUserId + " requested online characters");
var ownUser = DbContext.Users.Single(u => u.UID == AuthenticatedUserId); var ownUser = DbContext.Users.Single(u => u.UID == AuthenticatedUserId);
var otherUsers = await DbContext.ClientPairs var otherUsers = await DbContext.ClientPairs

View File

@@ -7,6 +7,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Bazinga.AspNetCore.Authentication.Basic" Version="2.0.1" /> <PackageReference Include="Bazinga.AspNetCore.Authentication.Basic" Version="2.0.1" />
<PackageReference Include="Karambolo.Extensions.Logging.File" Version="3.3.0" />
<PackageReference Include="lz4net" Version="1.0.15.93" /> <PackageReference Include="lz4net" Version="1.0.15.93" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="6.0.6" /> <PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="6.0.6" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.6" /> <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.6" />

View File

@@ -1,8 +1,12 @@
using System;
using System.IO;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using System.Linq; using System.Linq;
using System.Reflection;
using MareSynchronosServer.Data; using MareSynchronosServer.Data;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace MareSynchronosServer namespace MareSynchronosServer
{ {
@@ -36,6 +40,17 @@ namespace MareSynchronosServer
.UseConsoleLifetime() .UseConsoleLifetime()
.ConfigureWebHostDefaults(webBuilder => .ConfigureWebHostDefaults(webBuilder =>
{ {
webBuilder.UseContentRoot(AppContext.BaseDirectory);
webBuilder.ConfigureLogging((ctx, builder) =>
{
builder.AddSimpleConsole(options =>
{
options.SingleLine = true;
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss ";
});
builder.AddConfiguration(ctx.Configuration.GetSection("Logging"));
builder.AddFile(o => o.RootPath = AppContext.BaseDirectory);
});
webBuilder.UseStartup<Startup>(); webBuilder.UseStartup<Startup>();
}); });
} }

View File

@@ -39,7 +39,6 @@ namespace MareSynchronosServer
services.AddSingleton<IUserIdProvider, IdBasedUserIdProvider>(); services.AddSingleton<IUserIdProvider, IdBasedUserIdProvider>();
services.AddDbContext<MareDbContext>(options => services.AddDbContext<MareDbContext>(options =>
{ {
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")); options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));

View File

@@ -1,6 +1,6 @@
{ {
"ConnectionStrings": { "ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-MareSynchronosServer-BA82A12A-0B30-463C-801D-B7E81318CD50;Trusted_Connection=True;MultipleActiveResultSets=true" "DefaultConnection": "Server=(localdb)\\SQLEXPRESS;Database=mare;Trusted_Connection=True;MultipleActiveResultSets=true"
}, },
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {
@@ -9,20 +9,32 @@
"Microsoft.Hosting.Lifetime": "Information", "Microsoft.Hosting.Lifetime": "Information",
"MareSynchronosServer.Authentication": "Warning", "MareSynchronosServer.Authentication": "Warning",
"System.IO.IOException": "Warning" "System.IO.IOException": "Warning"
},
"File": {
"BasePath": "logs",
"FileAccessMode": "KeepOpenAndAutoFlush",
"FileEncodingName": "utf-8",
"DateFormat": "yyyMMdd",
"MaxFileSize": 10485760,
"Files": [
{
"Path": "mare-<counter>.log"
}
]
} }
}, },
"UnusedFileRetentionPeriodInDays" : 7, "UnusedFileRetentionPeriodInDays": 7,
"CacheDirectory": "G:\\ServerTest", // do not delete this key and set it to the path where the files will be stored "CacheDirectory": "G:\\ServerTest", // do not delete this key and set it to the path where the files will be stored
"AllowedHosts": "*", "AllowedHosts": "*",
"Kestrel": { "Kestrel": {
"Endpoints": { "Endpoints": {
"Https": { "Https": {
"Url": "https://+:5001", "Url": "https://+:5000",
"Certificate": { "Certificate": {
"Subject": "darkarchon.internet-box.ch", "Subject": "darkarchon.internet-box.ch",
"Store": "Root", "Store": "My",
"Location": "LocalMachine", "Location": "LocalMachine",
"AllowInvalid": false //"AllowInvalid": false
// "Path": "", //use path, keypath and password to provide a valid certificate if not using windows key store // "Path": "", //use path, keypath and password to provide a valid certificate if not using windows key store
// "KeyPath": "" // "KeyPath": ""
// "Password": "" // "Password": ""