diff --git a/MareSynchronosServer/MareSynchronos.API/BannedUserDto.cs b/MareSynchronosServer/MareSynchronos.API/BannedUserDto.cs index 2d5fc0a..0f58c5c 100644 --- a/MareSynchronosServer/MareSynchronos.API/BannedUserDto.cs +++ b/MareSynchronosServer/MareSynchronos.API/BannedUserDto.cs @@ -1,12 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace MareSynchronos.API +namespace MareSynchronos.API { - public class BannedUserDto + public record BannedUserDto { public string CharacterHash { get; set; } public string Reason { get; set; } diff --git a/MareSynchronosServer/MareSynchronos.API/CharacterCacheDto.cs b/MareSynchronosServer/MareSynchronos.API/CharacterCacheDto.cs index 7b22427..2873c32 100644 --- a/MareSynchronosServer/MareSynchronos.API/CharacterCacheDto.cs +++ b/MareSynchronosServer/MareSynchronos.API/CharacterCacheDto.cs @@ -1,13 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Newtonsoft.Json; +using System.Collections.Generic; namespace MareSynchronos.API { - public class CharacterCacheDto + public record CharacterCacheDto { public List FileReplacements { get; set; } = new(); public string GlamourerData { get; set; } @@ -15,10 +10,4 @@ namespace MareSynchronos.API public string Hash { get; set; } public int JobId { get; set; } } - - public class FileReplacementDto - { - public string[] GamePaths { get; set; } = Array.Empty(); - public string Hash { get; set; } - } } diff --git a/MareSynchronosServer/MareSynchronos.API/ClientPairDto.cs b/MareSynchronosServer/MareSynchronos.API/ClientPairDto.cs index dfa657f..598727f 100644 --- a/MareSynchronosServer/MareSynchronos.API/ClientPairDto.cs +++ b/MareSynchronosServer/MareSynchronos.API/ClientPairDto.cs @@ -1,6 +1,6 @@ namespace MareSynchronos.API { - public class ClientPairDto + public record ClientPairDto { public string OtherUID { get; set; } public bool IsPaused { get; set; } diff --git a/MareSynchronosServer/MareSynchronos.API/DownloadFileDto.cs b/MareSynchronosServer/MareSynchronos.API/DownloadFileDto.cs index a515b8a..483c2cc 100644 --- a/MareSynchronosServer/MareSynchronos.API/DownloadFileDto.cs +++ b/MareSynchronosServer/MareSynchronos.API/DownloadFileDto.cs @@ -1,12 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace MareSynchronos.API +namespace MareSynchronos.API { - public class DownloadFileDto + public record DownloadFileDto : ITransferFileDto { public bool FileExists { get; set; } = true; public string Hash { get; set; } = string.Empty; diff --git a/MareSynchronosServer/MareSynchronos.API/FileReplacementDto.cs b/MareSynchronosServer/MareSynchronos.API/FileReplacementDto.cs new file mode 100644 index 0000000..57aa2cb --- /dev/null +++ b/MareSynchronosServer/MareSynchronos.API/FileReplacementDto.cs @@ -0,0 +1,10 @@ +using System; + +namespace MareSynchronos.API +{ + public record FileReplacementDto + { + public string[] GamePaths { get; set; } = Array.Empty(); + public string Hash { get; set; } + } +} \ No newline at end of file diff --git a/MareSynchronosServer/MareSynchronos.API/ForbiddenUploadsDto.cs b/MareSynchronosServer/MareSynchronos.API/ForbiddenUploadsDto.cs index 50d5f42..d5bfa5c 100644 --- a/MareSynchronosServer/MareSynchronos.API/ForbiddenUploadsDto.cs +++ b/MareSynchronosServer/MareSynchronos.API/ForbiddenUploadsDto.cs @@ -1,12 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace MareSynchronos.API +namespace MareSynchronos.API { - public class ForbiddenFileDto + public record ForbiddenFileDto { public string Hash { get; set; } public string ForbiddenBy { get; set; } diff --git a/MareSynchronosServer/MareSynchronos.API/ITransferFileDto.cs b/MareSynchronosServer/MareSynchronos.API/ITransferFileDto.cs new file mode 100644 index 0000000..4ff8561 --- /dev/null +++ b/MareSynchronosServer/MareSynchronos.API/ITransferFileDto.cs @@ -0,0 +1,9 @@ +namespace MareSynchronos.API +{ + public interface ITransferFileDto + { + string Hash { get; set; } + bool IsForbidden { get; set; } + string ForbiddenBy { get; set; } + } +} \ No newline at end of file diff --git a/MareSynchronosServer/MareSynchronos.API/LoggedInUserDto.cs b/MareSynchronosServer/MareSynchronos.API/LoggedInUserDto.cs index 4644c0f..11323f1 100644 --- a/MareSynchronosServer/MareSynchronos.API/LoggedInUserDto.cs +++ b/MareSynchronosServer/MareSynchronos.API/LoggedInUserDto.cs @@ -1,12 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace MareSynchronos.API +namespace MareSynchronos.API { - public class LoggedInUserDto + public record LoggedInUserDto { public bool IsAdmin { get; set; } public bool IsModerator { get; set; } diff --git a/MareSynchronosServer/MareSynchronos.API/OnlineUserDto.cs b/MareSynchronosServer/MareSynchronos.API/OnlineUserDto.cs index 37dc325..78da994 100644 --- a/MareSynchronosServer/MareSynchronos.API/OnlineUserDto.cs +++ b/MareSynchronosServer/MareSynchronos.API/OnlineUserDto.cs @@ -1,12 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace MareSynchronos.API +namespace MareSynchronos.API { - public class OnlineUserDto + public record OnlineUserDto { public string UID { get; set; } public string CharacterNameHash { get; set; } diff --git a/MareSynchronosServer/MareSynchronos.API/UploadFileDto.cs b/MareSynchronosServer/MareSynchronos.API/UploadFileDto.cs index 01fb490..07ad783 100644 --- a/MareSynchronosServer/MareSynchronos.API/UploadFileDto.cs +++ b/MareSynchronosServer/MareSynchronos.API/UploadFileDto.cs @@ -1,12 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace MareSynchronos.API +namespace MareSynchronos.API { - public class UploadFileDto + public record UploadFileDto : ITransferFileDto { public string Hash { get; set; } = string.Empty; public bool IsForbidden { get; set; } = false; diff --git a/MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyAuthenticationHandler.cs b/MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyAuthenticationHandler.cs index ff03a58..f379dce 100644 --- a/MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyAuthenticationHandler.cs +++ b/MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyAuthenticationHandler.cs @@ -45,9 +45,16 @@ namespace MareSynchronosServer.Authentication return AuthenticateResult.Fail("Failed Authorization"); } - user.CharacterIdentification = charNameHeader; - _mareDbContext.Users.Update(user); - await _mareDbContext.SaveChangesAsync(); + if (user.CharacterIdentification != charNameHeader) + { + try + { + user.CharacterIdentification = charNameHeader; + _mareDbContext.Users.Update(user); + await _mareDbContext.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) { } + } var claims = new List { new Claim(ClaimTypes.Name, user.CharacterIdentification), diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/ConnectionHub.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/ConnectionHub.cs index 675e1c9..7cf3e9a 100644 --- a/MareSynchronosServer/MareSynchronosServer/Hubs/ConnectionHub.cs +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/ConnectionHub.cs @@ -17,10 +17,11 @@ namespace MareSynchronosServer.Hubs public async Task Heartbeat() { var userId = Context.User!.Claims.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value; - Logger.LogInformation("Heartbeat from " + (userId ?? "Unknown user")); + if (userId != null) { + Logger.LogInformation("Heartbeat from " + userId); var user = (await DbContext.Users.SingleAsync(u => u.UID == userId)); return new LoggedInUserDto { diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/UserHub.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/UserHub.cs index 296a83b..56985ea 100644 --- a/MareSynchronosServer/MareSynchronosServer/Hubs/UserHub.cs +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/UserHub.cs @@ -45,6 +45,13 @@ namespace MareSynchronosServer.Hubs user.UID = uid; hasValidUid = true; } + + // make the first registered user on the service to admin + if (!await DbContext.Users.AnyAsync()) + { + user.IsAdmin = true; + } + DbContext.Users.Add(user); Logger.LogInformation("User registered: " + user.UID); @@ -89,6 +96,28 @@ namespace MareSynchronosServer.Hubs } } + [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)] + public async Task PushCharacterDataToVisibleClients(CharacterCacheDto characterCache, List visibleCharacterIds) + { + Logger.LogInformation("User " + AuthenticatedUserId + " pushing character data to visible clients"); + + var uid = AuthenticatedUserId; + var entriesHavingThisUser = DbContext.ClientPairs + .Include(w => w.User) + .Include(w => w.OtherUser) + .Where(w => w.OtherUser.UID == uid && !w.IsPaused + && visibleCharacterIds.Contains(w.User.CharacterIdentification)).ToList(); + + foreach (var pair in entriesHavingThisUser) + { + var ownEntry = DbContext.ClientPairs.SingleOrDefault(w => + w.User.UID == uid && w.OtherUser.UID == pair.User.UID); + if (ownEntry == null || ownEntry.IsPaused) continue; + await Clients.User(pair.User.UID).SendAsync("ReceiveCharacterData", characterCache, + pair.OtherUser.CharacterIdentification); + } + } + [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)] public async Task PushCharacterData(CharacterCacheDto characterCache, List visibleCharacterIds) { @@ -152,7 +181,7 @@ namespace MareSynchronosServer.Hubs await Clients.Users(otherEntries.Select(e => e.User.UID)).SendAsync("AddOnlinePairedPlayer", ownUser.CharacterIdentification); await Clients.All.SendAsync("UsersOnline", await DbContext.Users.CountAsync(u => !string.IsNullOrEmpty(u.CharacterIdentification))); - return otherEntries.Select(e => e.User.CharacterIdentification).ToList(); + return otherEntries.Select(e => e.User.CharacterIdentification).Distinct().ToList(); } [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)] @@ -340,11 +369,6 @@ namespace MareSynchronosServer.Hubs { Logger.LogInformation("Disconnect from " + AuthenticatedUserId); - var outdatedCharacterData = DbContext.CharacterData.Where(v => v.UserId == user.UID); - DbContext.RemoveRange(outdatedCharacterData); - user.CharacterIdentification = null; - await DbContext.SaveChangesAsync(); - var otherUsers = DbContext.ClientPairs .Include(u => u.User) .Include(u => u.OtherUser) @@ -354,6 +378,12 @@ namespace MareSynchronosServer.Hubs var otherEntries = DbContext.ClientPairs.Include(u => u.User) .Where(u => otherUsers.Any(e => e == u.User) && u.OtherUser == user && !u.IsPaused).ToList(); await Clients.Users(otherEntries.Select(e => e.User.UID)).SendAsync("RemoveOnlinePairedPlayer", user.CharacterIdentification); + + var outdatedCharacterData = DbContext.CharacterData.Where(v => v.UserId == user.UID); + DbContext.RemoveRange(outdatedCharacterData); + user.CharacterIdentification = null; + await DbContext.SaveChangesAsync(); + await Clients.All.SendAsync("UsersOnline", await DbContext.Users.CountAsync(u => !string.IsNullOrEmpty(u.CharacterIdentification))); }