diff --git a/MareAPI b/MareAPI index a649b36..714d990 160000 --- a/MareAPI +++ b/MareAPI @@ -1 +1 @@ -Subproject commit a649b364955ce431f41c53c016823763febde708 +Subproject commit 714d990c0b5492cd2a19bb021f1570c6bc10e7c3 diff --git a/MareSynchronosServer/MareSynchronosServer/FileCleanupService.cs b/MareSynchronosServer/MareSynchronosServer/FileCleanupService.cs index 282b9c7..5feecf6 100644 --- a/MareSynchronosServer/MareSynchronosServer/FileCleanupService.cs +++ b/MareSynchronosServer/MareSynchronosServer/FileCleanupService.cs @@ -1,10 +1,13 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using MareSynchronosServer.Data; using MareSynchronosServer.Metrics; +using MareSynchronosServer.Models; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -60,7 +63,8 @@ namespace MareSynchronosServer { _logger.LogInformation("File does not exist anymore: " + fileName); dbContext.Files.Remove(file); - } else if (fi.LastAccessTime < prevTime) + } + else if (fi.LastAccessTime < prevTime) { MareMetrics.FilesTotalSize.Dec(fi.Length); _logger.LogInformation("File outdated: " + fileName); @@ -69,6 +73,67 @@ namespace MareSynchronosServer } } + if (!bool.TryParse(_configuration["PurgeUnusedAccounts"], out var purgeUnusedAccounts)) + { + purgeUnusedAccounts = false; + } + + if (purgeUnusedAccounts) + { + if (!int.TryParse(_configuration["PurgeUnusedAccountsPeriodInDays"], out var usersOlderThanDays)) + { + usersOlderThanDays = 14; + } + + _logger.LogInformation($"Cleaning up users older than {usersOlderThanDays} days"); + + var allUsers = dbContext.Users.ToList(); + List usersToRemove = new(); + foreach (var user in allUsers) + { + if (user.LastLoggedIn < (DateTime.Now - TimeSpan.FromDays(usersOlderThanDays))) + { + _logger.LogInformation("User outdated: " + user.UID); + usersToRemove.Add(user); + } + } + + foreach (var user in usersToRemove) + { + var auth = dbContext.Auth.Single(a => a.UserUID == user.UID); + + var userFiles = dbContext.Files.Where(f => f.Uploaded && f.Uploader.UID == user.UID).ToList(); + foreach (var file in userFiles) + { + var fi = new FileInfo(Path.Combine(_configuration["CacheDirectory"], file.Hash)); + if (fi.Exists) + { + MareMetrics.FilesTotalSize.Dec(fi.Length); + MareMetrics.FilesTotal.Dec(); + fi.Delete(); + } + } + + dbContext.Files.RemoveRange(userFiles); + + var ownPairData = dbContext.ClientPairs.Where(u => u.User.UID == user.UID).ToList(); + + dbContext.RemoveRange(ownPairData); + var otherPairData = dbContext.ClientPairs.Include(u => u.User) + .Where(u => u.OtherUser.UID == user.UID).ToList(); + + MareMetrics.Pairs.Dec(ownPairData.Count); + MareMetrics.PairsPaused.Dec(ownPairData.Count(c => c.IsPaused)); + MareMetrics.Pairs.Dec(otherPairData.Count); + MareMetrics.PairsPaused.Dec(otherPairData.Count(c => c.IsPaused)); + MareMetrics.UsersRegistered.Dec(); + + dbContext.RemoveRange(otherPairData); + dbContext.Remove(auth); + dbContext.Remove(user); + } + } + _logger.LogInformation($"Cleanup complete"); dbContext.SaveChanges(); diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Files.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Files.cs index 1b18b4e..a15a071 100644 --- a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Files.cs +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Files.cs @@ -53,32 +53,6 @@ namespace MareSynchronosServer.Hubs await _dbContext.SaveChangesAsync(); } - [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)] - [HubMethodName(Api.StreamFileDownloadFileAsync)] - public async IAsyncEnumerable DownloadFileAsync(string hash, [EnumeratorCancellation] CancellationToken ct) - { - _logger.LogInformation("User " + AuthenticatedUserId + " downloading file: " + hash); - - var file = _dbContext.Files.AsNoTracking() - .SingleOrDefault(f => f.Hash == hash); - if (file == null) yield break; - var chunkSize = 1024 * 512; // 512kb - int readByteCount; - var buffer = new byte[chunkSize]; - - var path = Path.Combine(BasePath, hash); - await using var fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read); - while ((readByteCount = fs.Read(buffer, 0, chunkSize)) > 0) - { - yield return readByteCount == chunkSize ? buffer.ToArray() : buffer.Take(readByteCount).ToArray(); - } - - _logger.LogInformation("User " + AuthenticatedUserId + " finished downloading file: " + hash); - - MareMetrics.UserDownloadedFiles.Inc(); - MareMetrics.UserDownloadedFilesSize.Inc(new FileInfo(path).Length); - } - [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)] [HubMethodName(Api.InvokeFileGetFileSize)] public async Task GetFileSize(string hash) diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs index 1313da8..d594e5d 100644 --- a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs @@ -26,6 +26,7 @@ namespace MareSynchronosServer.Hubs string userid = AuthenticatedUserId; var userEntry = await _dbContext.Users.SingleAsync(u => u.UID == userid); var ownPairData = await _dbContext.ClientPairs.Where(u => u.User.UID == userid).ToListAsync(); + var auth = await _dbContext.Auth.SingleAsync(u => u.UserUID == userid); MareMetrics.Pairs.Dec(ownPairData.Count); MareMetrics.PairsPaused.Dec(ownPairData.Count(c => c.IsPaused)); @@ -50,6 +51,7 @@ namespace MareSynchronosServer.Hubs _dbContext.RemoveRange(otherPairData); _dbContext.Remove(userEntry); + _dbContext.Remove(auth); await _dbContext.SaveChangesAsync(); } diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs index b7b74e4..9a4903d 100644 --- a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs @@ -41,7 +41,7 @@ namespace MareSynchronosServer.Hubs var isBanned = await _dbContext.BannedUsers.AsNoTracking().AnyAsync(u => u.CharacterIdentification == characterIdentification); - if (userId != null && !isBanned && !string.IsNullOrEmpty(characterIdentification)) + if (!string.IsNullOrEmpty(userId) && !isBanned && !string.IsNullOrEmpty(characterIdentification)) { _logger.LogInformation("Connection from " + userId); var user = (await _dbContext.Users.SingleAsync(u => u.UID == userId)); @@ -52,8 +52,11 @@ namespace MareSynchronosServer.Hubs ServerVersion = Api.Version }; } + else if (string.IsNullOrEmpty(user.CharacterIdentification)) + { + MareMetrics.AuthorizedConnections.Inc(); + } - MareMetrics.AuthorizedConnections.Inc(); user.LastLoggedIn = DateTime.UtcNow; user.CharacterIdentification = characterIdentification; await _dbContext.SaveChangesAsync(); @@ -109,9 +112,6 @@ namespace MareSynchronosServer.Hubs (await _dbContext.Users.SingleAsync(u => u.UID == AuthenticatedUserId)).CharacterIdentification = null; await _dbContext.SaveChangesAsync(); - - await Clients.All.SendAsync("UsersOnline", - await _dbContext.Users.CountAsync(u => !string.IsNullOrEmpty(u.CharacterIdentification))); } await base.OnDisconnectedAsync(exception); diff --git a/MareSynchronosServer/MareSynchronosServer/Program.cs b/MareSynchronosServer/MareSynchronosServer/Program.cs index 00ca479..c97897c 100644 --- a/MareSynchronosServer/MareSynchronosServer/Program.cs +++ b/MareSynchronosServer/MareSynchronosServer/Program.cs @@ -8,6 +8,8 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using MareSynchronosServer.Metrics; +using MareSynchronosServer.Models; +using System.Collections.Generic; namespace MareSynchronosServer { @@ -29,10 +31,10 @@ namespace MareSynchronosServer context.SaveChanges(); // clean up residuals - var users = context.Users.Where(u => u.CharacterIdentification != null); + var users = context.Users; foreach (var user in users) { - user.CharacterIdentification = string.Empty; + user.CharacterIdentification = null; } var looseFiles = context.Files.Where(f => f.Uploaded == false); context.RemoveRange(looseFiles); diff --git a/MareSynchronosServer/MareSynchronosServer/appsettings.json b/MareSynchronosServer/MareSynchronosServer/appsettings.json index b388893..28987c3 100644 --- a/MareSynchronosServer/MareSynchronosServer/appsettings.json +++ b/MareSynchronosServer/MareSynchronosServer/appsettings.json @@ -24,6 +24,8 @@ } }, "UnusedFileRetentionPeriodInDays": 7, + "PurgeUnusedAccounts": true, + "PurgeUnusedAccountsPeriodInDays": 14, "CacheDirectory": "G:\\ServerTest", // do not delete this key and set it to the path where the files will be stored "AllowedHosts": "*", "Kestrel": {