From 74b7fcdf8941e7f075efd1f4e1500f38d29853ae Mon Sep 17 00:00:00 2001 From: rootdarkarchon Date: Wed, 4 Jan 2023 15:49:18 +0100 Subject: [PATCH] Refactoring using Claims more, add Server Side Messaging (#20) * add some refactoring based on claims, handle chara ident inside claim, fix discord userid in log * improve authentication responses, add server side messaging * update server to mainline api Co-authored-by: rootdarkarchon --- MareAPI | 2 +- .../Authentication/SecretKeyAuthReply.cs | 3 + .../SecretKeyAuthenticatorService.cs | 12 +-- .../SecretKeyFailedAuthorization.cs | 2 +- .../Controllers/JwtController.cs | 46 +++++++- .../Hubs/MareClaimTypes.cs | 7 ++ .../Hubs/MareHub.ClientStubs.cs | 5 + .../Hubs/MareHub.Files.cs | 15 ++- .../Hubs/MareHub.Functions.cs | 16 +-- .../Hubs/MareHub.Groups.cs | 65 ++++++------ .../MareSynchronosServer/Hubs/MareHub.User.cs | 82 +++++++------- .../MareSynchronosServer/Hubs/MareHub.cs | 100 ++++++++---------- .../Hubs/SignalRLimitFilter.cs | 5 +- .../UserRequirementHandler.cs | 6 +- .../Services/ClientMessageService.cs | 46 ++++++++ .../GrpcClientIdentificationService.cs | 4 +- .../Services/SystemInfoService.cs | 12 +-- .../MareSynchronosServer/Startup.cs | 7 +- .../Utils/IdBasedUserIdProvider.cs | 4 +- .../Utils/MareHubLogger.cs | 4 +- .../Discord/MareModule.cs | 73 ++++++++++--- .../MareSynchronosServices/Startup.cs | 12 +++ .../Authentication/SecretKeyAuthReply.cs | 3 - .../Protos/mareservices.proto | 16 +++ .../Startup.cs | 7 -- 25 files changed, 350 insertions(+), 204 deletions(-) create mode 100644 MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyAuthReply.cs rename MareSynchronosServer/{MareSynchronosShared => MareSynchronosServer}/Authentication/SecretKeyAuthenticatorService.cs (92%) rename MareSynchronosServer/{MareSynchronosShared => MareSynchronosServer}/Authentication/SecretKeyFailedAuthorization.cs (84%) create mode 100644 MareSynchronosServer/MareSynchronosServer/Hubs/MareClaimTypes.cs create mode 100644 MareSynchronosServer/MareSynchronosServer/Services/ClientMessageService.cs delete mode 100644 MareSynchronosServer/MareSynchronosShared/Authentication/SecretKeyAuthReply.cs diff --git a/MareAPI b/MareAPI index 6645eaf..d361cfa 160000 --- a/MareAPI +++ b/MareAPI @@ -1 +1 @@ -Subproject commit 6645eaf63fe7c44669f0d62ab95003bcf1d3d04d +Subproject commit d361cfa3b983e8772c2bd08b3d638542ed57cd0f diff --git a/MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyAuthReply.cs b/MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyAuthReply.cs new file mode 100644 index 0000000..3a0b84b --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyAuthReply.cs @@ -0,0 +1,3 @@ +namespace MareSynchronosServer.Authentication; + +public record SecretKeyAuthReply(bool Success, string Uid, bool TempBan); diff --git a/MareSynchronosServer/MareSynchronosShared/Authentication/SecretKeyAuthenticatorService.cs b/MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyAuthenticatorService.cs similarity index 92% rename from MareSynchronosServer/MareSynchronosShared/Authentication/SecretKeyAuthenticatorService.cs rename to MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyAuthenticatorService.cs index 697209d..fa60fc8 100644 --- a/MareSynchronosServer/MareSynchronosShared/Authentication/SecretKeyAuthenticatorService.cs +++ b/MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyAuthenticatorService.cs @@ -4,10 +4,8 @@ using MareSynchronosShared.Metrics; using MareSynchronosShared.Services; using MareSynchronosShared.Utils; using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -namespace MareSynchronosShared.Authentication; +namespace MareSynchronosServer.Authentication; public class SecretKeyAuthenticatorService { @@ -16,7 +14,7 @@ public class SecretKeyAuthenticatorService private readonly IConfigurationService _configurationService; private readonly ILogger _logger; private readonly ConcurrentDictionary _cachedPositiveResponses = new(StringComparer.Ordinal); - private readonly ConcurrentDictionary _failedAuthorizations = new(StringComparer.Ordinal); + private readonly ConcurrentDictionary _failedAuthorizations = new(StringComparer.Ordinal); public SecretKeyAuthenticatorService(MareMetrics metrics, IServiceScopeFactory serviceScopeFactory, IConfigurationService configuration, ILogger logger) { @@ -52,14 +50,14 @@ public class SecretKeyAuthenticatorService _failedAuthorizations.Remove(ip, out _); }); } - return new(Success: false, Uid: null); + return new(Success: false, Uid: null, TempBan: true); } using var scope = _serviceScopeFactory.CreateScope(); using var context = scope.ServiceProvider.GetService(); var authReply = await context.Auth.AsNoTracking().SingleOrDefaultAsync(u => u.HashedKey == hashedSecretKey).ConfigureAwait(false); - SecretKeyAuthReply reply = new(authReply != null, authReply?.UserUID); + SecretKeyAuthReply reply = new(authReply != null, authReply?.UserUID, false); if (reply.Success) { @@ -99,6 +97,6 @@ public class SecretKeyAuthenticatorService } } - return new(Success: false, Uid: null); + return new(Success: false, Uid: null, TempBan: false); } } diff --git a/MareSynchronosServer/MareSynchronosShared/Authentication/SecretKeyFailedAuthorization.cs b/MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyFailedAuthorization.cs similarity index 84% rename from MareSynchronosServer/MareSynchronosShared/Authentication/SecretKeyFailedAuthorization.cs rename to MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyFailedAuthorization.cs index 3dc19a2..a5bae15 100644 --- a/MareSynchronosServer/MareSynchronosShared/Authentication/SecretKeyFailedAuthorization.cs +++ b/MareSynchronosServer/MareSynchronosServer/Authentication/SecretKeyFailedAuthorization.cs @@ -1,4 +1,4 @@ -namespace MareSynchronosShared.Authentication; +namespace MareSynchronosServer.Authentication; internal record SecretKeyFailedAuthorization { diff --git a/MareSynchronosServer/MareSynchronosServer/Controllers/JwtController.cs b/MareSynchronosServer/MareSynchronosServer/Controllers/JwtController.cs index 966419b..f061a53 100644 --- a/MareSynchronosServer/MareSynchronosServer/Controllers/JwtController.cs +++ b/MareSynchronosServer/MareSynchronosServer/Controllers/JwtController.cs @@ -1,10 +1,14 @@ using MareSynchronos.API; +using MareSynchronosServer.Authentication; +using MareSynchronosServer.Hubs; +using MareSynchronosServer.Services; using MareSynchronosShared; -using MareSynchronosShared.Authentication; +using MareSynchronosShared.Data; using MareSynchronosShared.Services; using MareSynchronosShared.Utils; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; @@ -17,14 +21,50 @@ namespace MareSynchronosServer.Controllers; public class JwtController : Controller { private readonly IHttpContextAccessor _accessor; + private readonly MareDbContext _mareDbContext; private readonly SecretKeyAuthenticatorService _secretKeyAuthenticatorService; private readonly IConfigurationService _configuration; + private readonly IClientIdentificationService _clientIdentService; - public JwtController(IHttpContextAccessor accessor, SecretKeyAuthenticatorService secretKeyAuthenticatorService, IConfigurationService configuration) + public JwtController(IHttpContextAccessor accessor, MareDbContext mareDbContext, + SecretKeyAuthenticatorService secretKeyAuthenticatorService, + IConfigurationService configuration, + IClientIdentificationService clientIdentService) { _accessor = accessor; + _mareDbContext = mareDbContext; _secretKeyAuthenticatorService = secretKeyAuthenticatorService; _configuration = configuration; + _clientIdentService = clientIdentService; + } + + [AllowAnonymous] + [HttpPost(MareAuth.AuthCreateIdent)] + public async Task CreateToken(string auth, string charaIdent) + { + if (string.IsNullOrEmpty(auth)) return BadRequest("No Authkey"); + if (string.IsNullOrEmpty(charaIdent)) return BadRequest("No CharaIdent"); + + var isBanned = await _mareDbContext.BannedUsers.AsNoTracking().AnyAsync(u => u.CharacterIdentification == charaIdent).ConfigureAwait(false); + if (isBanned) return Unauthorized("Your character is banned from using the service."); + + var ip = _accessor.GetIpAddress(); + + var authResult = await _secretKeyAuthenticatorService.AuthorizeAsync(ip, auth); + + if (!authResult.Success && !authResult.TempBan) return Unauthorized("The provided secret key is invalid. Verify your accounts existence and/or recover the secret key."); + if (!authResult.Success && authResult.TempBan) return Unauthorized("You are temporarily banned. Try connecting again later."); + + var existingIdent = _clientIdentService.GetCharacterIdentForUid(authResult.Uid); + if (!string.IsNullOrEmpty(existingIdent)) return Unauthorized("Already logged in to this account."); + + var token = CreateToken(new List() + { + new Claim(MareClaimTypes.Uid, authResult.Uid), + new Claim(MareClaimTypes.CharaIdent, charaIdent) + }); + + return Content(token.RawData); } [AllowAnonymous] @@ -41,7 +81,7 @@ public class JwtController : Controller var token = CreateToken(new List() { - new Claim(ClaimTypes.NameIdentifier, authResult.Uid) + new Claim(MareClaimTypes.Uid, authResult.Uid) }); return Content(token.RawData); diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/MareClaimTypes.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/MareClaimTypes.cs new file mode 100644 index 0000000..2c11442 --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/MareClaimTypes.cs @@ -0,0 +1,7 @@ +namespace MareSynchronosServer.Hubs; + +public static class MareClaimTypes +{ + public const string Uid = "uid"; + public const string CharaIdent = "character_identification"; +} diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.ClientStubs.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.ClientStubs.cs index db665cf..14ea0b3 100644 --- a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.ClientStubs.cs +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.ClientStubs.cs @@ -58,5 +58,10 @@ namespace MareSynchronosServer.Hubs { throw new PlatformNotSupportedException("Calling clientside method on server not supported"); } + + public Task Client_ReceiveServerMessage(MessageSeverity messageSeverity, string message) + { + throw new PlatformNotSupportedException("Calling clientside method on server not supported"); + } } } diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Files.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Files.cs index 73fe814..3966c9d 100644 --- a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Files.cs +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Files.cs @@ -21,8 +21,7 @@ public partial class MareHub public async Task FilesAbortUpload() { _logger.LogCallInfo(); - var userId = AuthenticatedUserId; - var notUploadedFiles = _dbContext.Files.Where(f => !f.Uploaded && f.Uploader.UID == userId).ToList(); + var notUploadedFiles = _dbContext.Files.Where(f => !f.Uploaded && f.Uploader.UID == UserUID).ToList(); _dbContext.RemoveRange(notUploadedFiles); await _dbContext.SaveChangesAsync().ConfigureAwait(false); } @@ -32,7 +31,7 @@ public partial class MareHub { _logger.LogCallInfo(); - var ownFiles = await _dbContext.Files.Where(f => f.Uploaded && f.Uploader.UID == AuthenticatedUserId).ToListAsync().ConfigureAwait(false); + var ownFiles = await _dbContext.Files.Where(f => f.Uploaded && f.Uploader.UID == UserUID).ToListAsync().ConfigureAwait(false); var request = new DeleteFilesRequest(); request.Hash.AddRange(ownFiles.Select(f => f.Hash)); Metadata headers = new Metadata() @@ -81,9 +80,8 @@ public partial class MareHub public async Task FilesIsUploadFinished() { _logger.LogCallInfo(); - var userUid = AuthenticatedUserId; return await _dbContext.Files.AsNoTracking() - .AnyAsync(f => f.Uploader.UID == userUid && !f.Uploaded).ConfigureAwait(false); + .AnyAsync(f => f.Uploader.UID == UserUID && !f.Uploaded).ConfigureAwait(false); } [Authorize(Policy = "Identified")] @@ -94,7 +92,7 @@ public partial class MareHub var notCoveredFiles = new Dictionary(StringComparer.Ordinal); var forbiddenFiles = await _dbContext.ForbiddenUploadEntries.AsNoTracking().Where(f => userSentHashes.Contains(f.Hash)).AsNoTracking().ToDictionaryAsync(f => f.Hash, f => f).ConfigureAwait(false); var existingFiles = await _dbContext.Files.AsNoTracking().Where(f => userSentHashes.Contains(f.Hash)).AsNoTracking().ToDictionaryAsync(f => f.Hash, f => f).ConfigureAwait(false); - var uploader = await _dbContext.Users.SingleAsync(u => u.UID == AuthenticatedUserId).ConfigureAwait(false); + var uploader = await _dbContext.Users.SingleAsync(u => u.UID == UserUID).ConfigureAwait(false); List fileCachesToUpload = new(); foreach (var file in userSentHashes) @@ -117,7 +115,6 @@ public partial class MareHub _logger.LogCallInfo(MareHubLogger.Args(file, "Missing")); - var userId = AuthenticatedUserId; fileCachesToUpload.Add(new FileCache() { Hash = file, @@ -143,7 +140,7 @@ public partial class MareHub await _uploadSemaphore.WaitAsync(Context.ConnectionAborted).ConfigureAwait(false); - var relatedFile = _dbContext.Files.SingleOrDefault(f => f.Hash == hash && f.Uploader.UID == AuthenticatedUserId && !f.Uploaded); + var relatedFile = _dbContext.Files.SingleOrDefault(f => f.Hash == hash && f.Uploader.UID == UserUID && !f.Uploaded); if (relatedFile == null) { _uploadSemaphore.Release(); @@ -226,7 +223,7 @@ public partial class MareHub { FileData = ByteString.CopyFrom(data, 0, readBytes), Hash = computedHashString, - Uploader = AuthenticatedUserId + Uploader = UserUID }).ConfigureAwait(false); } await streamingCall.RequestStream.CompleteAsync().ConfigureAwait(false); diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Functions.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Functions.cs index c6ca28b..f370195 100644 --- a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Functions.cs +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Functions.cs @@ -1,7 +1,6 @@ using MareSynchronosShared.Models; using Microsoft.EntityFrameworkCore; using MareSynchronosServer.Utils; -using System.Security.Claims; namespace MareSynchronosServer.Hubs; @@ -9,7 +8,7 @@ public partial class MareHub { private async Task> GetAllPairedClientsWithPauseState(string? uid = null) { - uid ??= AuthenticatedUserId; + uid ??= UserUID; var query = await (from userPair in _dbContext.ClientPairs join otherUserPair in _dbContext.ClientPairs on userPair.OtherUserUID equals otherUserPair.UserUID @@ -47,7 +46,7 @@ public partial class MareHub private async Task> GetAllPairedUnpausedUsers(string? uid = null) { - uid ??= AuthenticatedUserId; + uid ??= UserUID; var ret = await GetAllPairedClientsWithPauseState(uid).ConfigureAwait(false); return ret.Where(k => !k.IsPaused).Select(k => k.UID).ToList(); } @@ -68,11 +67,12 @@ public partial class MareHub return usersToSendDataTo; } - public string AuthenticatedUserId => Context.User?.Claims?.SingleOrDefault(c => string.Equals(c.Type, ClaimTypes.NameIdentifier, StringComparison.Ordinal))?.Value ?? "Unknown"; + public string UserUID => Context.User?.Claims?.SingleOrDefault(c => string.Equals(c.Type, MareClaimTypes.Uid, StringComparison.Ordinal))?.Value ?? throw new Exception("No UID in Claims"); + public string UserCharaIdent => Context.User?.Claims?.SingleOrDefault(c => string.Equals(c.Type, MareClaimTypes.CharaIdent, StringComparison.Ordinal))?.Value ?? throw new Exception("No Chara Ident in Claims"); private async Task UserGroupLeave(GroupPair groupUserPair, List allUserPairs, string userIdent, string? uid = null) { - uid ??= AuthenticatedUserId; + uid ??= UserUID; var userPair = allUserPairs.SingleOrDefault(p => string.Equals(p.UID, groupUserPair.GroupUserUID, StringComparison.Ordinal)); if (userPair != null) { @@ -106,7 +106,7 @@ public partial class MareHub private async Task<(bool IsValid, GroupPair ReferredPair)> TryValidateUserInGroup(string gid, string? uid = null) { - uid ??= AuthenticatedUserId; + uid ??= UserUID; var groupPair = await _dbContext.GroupPairs.Include(c => c.GroupUser) .SingleOrDefaultAsync(g => g.GroupGID == gid && (g.GroupUserUID == uid || g.GroupUser.Alias == uid)).ConfigureAwait(false); @@ -122,7 +122,7 @@ public partial class MareHub if (isOwnerResult.ReferredGroup == null) return (false, null); - var groupPairSelf = await _dbContext.GroupPairs.SingleOrDefaultAsync(g => g.GroupGID == gid && g.GroupUserUID == AuthenticatedUserId).ConfigureAwait(false); + var groupPairSelf = await _dbContext.GroupPairs.SingleOrDefaultAsync(g => g.GroupGID == gid && g.GroupUserUID == UserUID).ConfigureAwait(false); if (groupPairSelf == null || !groupPairSelf.IsModerator) return (false, null); return (true, isOwnerResult.ReferredGroup); @@ -133,6 +133,6 @@ public partial class MareHub var group = await _dbContext.Groups.SingleOrDefaultAsync(g => g.GID == gid).ConfigureAwait(false); if (group == null) return (false, null); - return (string.Equals(group.OwnerUID, AuthenticatedUserId, StringComparison.Ordinal), group); + return (string.Equals(group.OwnerUID, UserUID, StringComparison.Ordinal), group); } } diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Groups.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Groups.cs index bfd2132..02f1f96 100644 --- a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Groups.cs +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Groups.cs @@ -15,8 +15,8 @@ public partial class MareHub public async Task GroupCreate() { _logger.LogCallInfo(); - var existingGroupsByUser = await _dbContext.Groups.CountAsync(u => u.OwnerUID == AuthenticatedUserId).ConfigureAwait(false); - var existingJoinedGroups = await _dbContext.GroupPairs.CountAsync(u => u.GroupUserUID == AuthenticatedUserId).ConfigureAwait(false); + var existingGroupsByUser = await _dbContext.Groups.CountAsync(u => u.OwnerUID == UserUID).ConfigureAwait(false); + var existingJoinedGroups = await _dbContext.GroupPairs.CountAsync(u => u.GroupUserUID == UserUID).ConfigureAwait(false); if (existingGroupsByUser >= _maxExistingGroupsByUser || existingJoinedGroups >= _maxJoinedGroupsByUser) { throw new System.Exception($"Max groups for user is {_maxExistingGroupsByUser}, max joined groups is {_maxJoinedGroupsByUser}."); @@ -38,13 +38,13 @@ public partial class MareHub GID = gid, HashedPassword = hashedPw, InvitesEnabled = true, - OwnerUID = AuthenticatedUserId + OwnerUID = UserUID }; GroupPair initialPair = new() { GroupGID = newGroup.GID, - GroupUserUID = AuthenticatedUserId, + GroupUserUID = UserUID, IsPaused = false, IsPinned = true }; @@ -53,9 +53,9 @@ public partial class MareHub await _dbContext.GroupPairs.AddAsync(initialPair).ConfigureAwait(false); await _dbContext.SaveChangesAsync().ConfigureAwait(false); - var self = await _dbContext.Users.SingleAsync(u => u.UID == AuthenticatedUserId).ConfigureAwait(false); + var self = await _dbContext.Users.SingleAsync(u => u.UID == UserUID).ConfigureAwait(false); - await Clients.User(AuthenticatedUserId).Client_GroupChange(new GroupDto() + await Clients.User(UserUID).Client_GroupChange(new GroupDto() { GID = newGroup.GID, OwnedBy = string.IsNullOrEmpty(self.Alias) ? self.UID : self.Alias, @@ -78,7 +78,7 @@ public partial class MareHub { _logger.LogCallInfo(); - var groups = await _dbContext.GroupPairs.Include(g => g.Group).Include(g => g.Group.Owner).Where(g => g.GroupUserUID == AuthenticatedUserId).AsNoTracking().ToListAsync().ConfigureAwait(false); + var groups = await _dbContext.GroupPairs.Include(g => g.Group).Include(g => g.Group.Owner).Where(g => g.GroupUserUID == UserUID).AsNoTracking().ToListAsync().ConfigureAwait(false); return groups.Select(g => new GroupDto() { @@ -99,7 +99,7 @@ public partial class MareHub var (inGroup, _) = await TryValidateUserInGroup(gid).ConfigureAwait(false); if (!inGroup) return new List(); - var allPairs = await _dbContext.GroupPairs.Include(g => g.GroupUser).Where(g => g.GroupGID == gid && g.GroupUserUID != AuthenticatedUserId).AsNoTracking().ToListAsync().ConfigureAwait(false); + var allPairs = await _dbContext.GroupPairs.Include(g => g.GroupUser).Where(g => g.GroupGID == gid && g.GroupUserUID != UserUID).AsNoTracking().ToListAsync().ConfigureAwait(false); return allPairs.Select(p => new GroupPairDto() { GroupGID = gid, @@ -160,14 +160,16 @@ public partial class MareHub [Authorize(Policy = "Identified")] public async Task GroupJoin(string gid, string password) { + gid = gid.Trim(); + _logger.LogCallInfo(MareHubLogger.Args(gid)); var group = await _dbContext.Groups.Include(g => g.Owner).AsNoTracking().SingleOrDefaultAsync(g => g.GID == gid || g.Alias == gid).ConfigureAwait(false); - var existingPair = await _dbContext.GroupPairs.AsNoTracking().SingleOrDefaultAsync(g => g.GroupGID == gid && g.GroupUserUID == AuthenticatedUserId).ConfigureAwait(false); + var existingPair = await _dbContext.GroupPairs.AsNoTracking().SingleOrDefaultAsync(g => g.GroupGID == gid && g.GroupUserUID == UserUID).ConfigureAwait(false); var hashedPw = StringUtils.Sha256String(password); var existingUserCount = await _dbContext.GroupPairs.AsNoTracking().CountAsync(g => g.GroupGID == gid).ConfigureAwait(false); - var joinedGroups = await _dbContext.GroupPairs.CountAsync(g => g.GroupUserUID == AuthenticatedUserId).ConfigureAwait(false); - var isBanned = await _dbContext.GroupBans.AnyAsync(g => g.GroupGID == gid && g.BannedUserUID == AuthenticatedUserId).ConfigureAwait(false); + var joinedGroups = await _dbContext.GroupPairs.CountAsync(g => g.GroupUserUID == UserUID).ConfigureAwait(false); + var isBanned = await _dbContext.GroupBans.AnyAsync(g => g.GroupGID == gid && g.BannedUserUID == UserUID).ConfigureAwait(false); var groupGid = group?.GID ?? string.Empty; var oneTimeInvite = await _dbContext.GroupTempInvites.SingleOrDefaultAsync(g => g.GroupGID == groupGid && g.Invite == hashedPw).ConfigureAwait(false); @@ -189,7 +191,7 @@ public partial class MareHub GroupPair newPair = new() { GroupGID = group.GID, - GroupUserUID = AuthenticatedUserId + GroupUserUID = UserUID }; await _dbContext.GroupPairs.AddAsync(newPair).ConfigureAwait(false); @@ -197,7 +199,7 @@ public partial class MareHub _logger.LogCallInfo(MareHubLogger.Args(gid, "Success")); - await Clients.User(AuthenticatedUserId).Client_GroupChange(new GroupDto() + await Clients.User(UserUID).Client_GroupChange(new GroupDto() { GID = group.GID, OwnedBy = string.IsNullOrEmpty(group.Owner.Alias) ? group.Owner.UID : group.Owner.Alias, @@ -207,15 +209,15 @@ public partial class MareHub InvitesEnabled = true }).ConfigureAwait(false); - var self = _dbContext.Users.Single(u => u.UID == AuthenticatedUserId); + var self = _dbContext.Users.Single(u => u.UID == UserUID); - var groupPairs = await _dbContext.GroupPairs.Where(p => p.GroupGID == group.GID && p.GroupUserUID != AuthenticatedUserId).ToListAsync().ConfigureAwait(false); + var groupPairs = await _dbContext.GroupPairs.Where(p => p.GroupGID == group.GID && p.GroupUserUID != UserUID).ToListAsync().ConfigureAwait(false); await Clients.Users(groupPairs.Select(p => p.GroupUserUID)).Client_GroupUserChange(new GroupPairDto() { GroupGID = group.GID, IsPaused = false, IsRemoved = false, - UserUID = AuthenticatedUserId, + UserUID = UserUID, UserAlias = self.Alias, IsPinned = false, IsModerator = false, @@ -223,7 +225,6 @@ public partial class MareHub var allUserPairs = await GetAllPairedClientsWithPauseState().ConfigureAwait(false); - var userIdent = _clientIdentService.GetCharacterIdentForUid(AuthenticatedUserId); foreach (var groupUserPair in groupPairs) { var userPair = allUserPairs.Single(p => string.Equals(p.UID, groupUserPair.GroupUserUID, StringComparison.Ordinal)); @@ -234,8 +235,8 @@ public partial class MareHub var groupUserIdent = _clientIdentService.GetCharacterIdentForUid(groupUserPair.GroupUserUID); if (!string.IsNullOrEmpty(groupUserIdent)) { - await Clients.User(AuthenticatedUserId).Client_UserChangePairedPlayer(groupUserIdent, true).ConfigureAwait(false); - await Clients.User(groupUserPair.GroupUserUID).Client_UserChangePairedPlayer(userIdent, true).ConfigureAwait(false); + await Clients.User(UserUID).Client_UserChangePairedPlayer(groupUserIdent, true).ConfigureAwait(false); + await Clients.User(groupUserPair.GroupUserUID).Client_UserChangePairedPlayer(UserCharaIdent, true).ConfigureAwait(false); } } @@ -292,18 +293,18 @@ public partial class MareHub var group = await _dbContext.Groups.SingleOrDefaultAsync(g => g.GID == gid).ConfigureAwait(false); var groupPairs = await _dbContext.GroupPairs.Where(p => p.GroupGID == group.GID).ToListAsync().ConfigureAwait(false); - var groupPairsWithoutSelf = groupPairs.Where(p => !string.Equals(p.GroupUserUID, AuthenticatedUserId, StringComparison.Ordinal)).ToList(); + var groupPairsWithoutSelf = groupPairs.Where(p => !string.Equals(p.GroupUserUID, UserUID, StringComparison.Ordinal)).ToList(); _dbContext.GroupPairs.Remove(groupPair); await _dbContext.SaveChangesAsync().ConfigureAwait(false); - await Clients.User(AuthenticatedUserId).Client_GroupChange(new GroupDto() + await Clients.User(UserUID).Client_GroupChange(new GroupDto() { GID = group.GID, IsDeleted = true }).ConfigureAwait(false); - bool ownerHasLeft = string.Equals(group.OwnerUID, AuthenticatedUserId, StringComparison.Ordinal); + bool ownerHasLeft = string.Equals(group.OwnerUID, UserUID, StringComparison.Ordinal); if (ownerHasLeft) { if (!groupPairsWithoutSelf.Any()) @@ -352,15 +353,14 @@ public partial class MareHub { GroupGID = group.GID, IsRemoved = true, - UserUID = AuthenticatedUserId, + UserUID = UserUID, }).ConfigureAwait(false); var allUserPairs = await GetAllPairedClientsWithPauseState().ConfigureAwait(false); - var userIdent = _clientIdentService.GetCharacterIdentForUid(AuthenticatedUserId); foreach (var groupUserPair in groupPairsWithoutSelf) { - await UserGroupLeave(groupUserPair, allUserPairs, userIdent).ConfigureAwait(false); + await UserGroupLeave(groupUserPair, allUserPairs, UserCharaIdent).ConfigureAwait(false); } } @@ -377,15 +377,15 @@ public partial class MareHub _logger.LogCallInfo(MareHubLogger.Args(gid, isPaused, "Success")); - var groupPairs = await _dbContext.GroupPairs.Where(p => p.GroupGID == gid && p.GroupUserUID != AuthenticatedUserId).AsNoTracking().ToListAsync().ConfigureAwait(false); + var groupPairs = await _dbContext.GroupPairs.Where(p => p.GroupGID == gid && p.GroupUserUID != UserUID).AsNoTracking().ToListAsync().ConfigureAwait(false); await Clients.Users(groupPairs.Select(p => p.GroupUserUID)).Client_GroupUserChange(new GroupPairDto() { GroupGID = gid, IsPaused = isPaused, - UserUID = AuthenticatedUserId, + UserUID = UserUID, }).ConfigureAwait(false); - await Clients.User(AuthenticatedUserId).Client_GroupChange(new GroupDto + await Clients.User(UserUID).Client_GroupChange(new GroupDto { GID = gid, IsPaused = isPaused @@ -393,7 +393,6 @@ public partial class MareHub var allUserPairs = await GetAllPairedClientsWithPauseState().ConfigureAwait(false); - var userIdent = _clientIdentService.GetCharacterIdentForUid(AuthenticatedUserId); foreach (var groupUserPair in groupPairs) { var userPair = allUserPairs.SingleOrDefault(p => string.Equals(p.UID, groupUserPair.GroupUserUID, StringComparison.Ordinal)); @@ -407,8 +406,8 @@ public partial class MareHub var groupUserIdent = _clientIdentService.GetCharacterIdentForUid(groupUserPair.GroupUserUID); if (!string.IsNullOrEmpty(groupUserIdent)) { - await Clients.User(AuthenticatedUserId).Client_UserChangePairedPlayer(groupUserIdent, !isPaused).ConfigureAwait(false); - await Clients.User(groupUserPair.GroupUserUID).Client_UserChangePairedPlayer(userIdent, !isPaused).ConfigureAwait(false); + await Clients.User(UserUID).Client_UserChangePairedPlayer(groupUserIdent, !isPaused).ConfigureAwait(false); + await Clients.User(groupUserPair.GroupUserUID).Client_UserChangePairedPlayer(UserCharaIdent, !isPaused).ConfigureAwait(false); } } } @@ -471,7 +470,7 @@ public partial class MareHub var alias = string.IsNullOrEmpty(groupPair.GroupUser.Alias) ? "-" : groupPair.GroupUser.Alias; var ban = new GroupBan() { - BannedByUID = AuthenticatedUserId, + BannedByUID = UserUID, BannedReason = $"{reason} (Alias at time of ban: {alias})", BannedOn = DateTime.UtcNow, BannedUserUID = uid, @@ -574,7 +573,7 @@ public partial class MareHub var ownedShells = await _dbContext.Groups.CountAsync(g => g.OwnerUID == uid).ConfigureAwait(false); if (ownedShells >= _maxExistingGroupsByUser) return; - var prevOwner = await _dbContext.GroupPairs.SingleOrDefaultAsync(g => g.GroupGID == gid && g.GroupUserUID == AuthenticatedUserId).ConfigureAwait(false); + var prevOwner = await _dbContext.GroupPairs.SingleOrDefaultAsync(g => g.GroupGID == gid && g.GroupUserUID == UserUID).ConfigureAwait(false); prevOwner.IsPinned = false; group.Owner = newOwnerPair.GroupUser; group.Alias = null; diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs index 2016703..eb622a3 100644 --- a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs @@ -16,13 +16,11 @@ public partial class MareHub { _logger.LogCallInfo(); - string userid = AuthenticatedUserId; - var userEntry = await _dbContext.Users.SingleAsync(u => u.UID == userid).ConfigureAwait(false); - var charaIdent = _clientIdentService.GetCharacterIdentForUid(userid); - var ownPairData = await _dbContext.ClientPairs.Where(u => u.User.UID == userid).ToListAsync().ConfigureAwait(false); - var auth = await _dbContext.Auth.SingleAsync(u => u.UserUID == userid).ConfigureAwait(false); - var lodestone = await _dbContext.LodeStoneAuth.SingleOrDefaultAsync(a => a.User.UID == userid).ConfigureAwait(false); - var groupPairs = await _dbContext.GroupPairs.Where(g => g.GroupUserUID == userid).ToListAsync().ConfigureAwait(false); + var userEntry = await _dbContext.Users.SingleAsync(u => u.UID == UserUID).ConfigureAwait(false); + var ownPairData = await _dbContext.ClientPairs.Where(u => u.User.UID == UserUID).ToListAsync().ConfigureAwait(false); + var auth = await _dbContext.Auth.SingleAsync(u => u.UserUID == UserUID).ConfigureAwait(false); + var lodestone = await _dbContext.LodeStoneAuth.SingleOrDefaultAsync(a => a.User.UID == UserUID).ConfigureAwait(false); + var groupPairs = await _dbContext.GroupPairs.Where(g => g.GroupUserUID == UserUID).ToListAsync().ConfigureAwait(false); if (lodestone != null) { @@ -37,12 +35,12 @@ public partial class MareHub _dbContext.ClientPairs.RemoveRange(ownPairData); await _dbContext.SaveChangesAsync().ConfigureAwait(false); var otherPairData = await _dbContext.ClientPairs.Include(u => u.User) - .Where(u => u.OtherUser.UID == userid).AsNoTracking().ToListAsync().ConfigureAwait(false); + .Where(u => u.OtherUser.UID == UserUID).AsNoTracking().ToListAsync().ConfigureAwait(false); foreach (var pair in otherPairData) { await Clients.User(pair.User.UID).Client_UserUpdateClientPairs(new ClientPairDto() { - OtherUID = userid, + OtherUID = UserUID, IsRemoved = true }).ConfigureAwait(false); } @@ -65,9 +63,7 @@ public partial class MareHub { _logger.LogCallInfo(); - var ownIdent = _clientIdentService.GetCharacterIdentForUid(AuthenticatedUserId); - - var usersToSendOnlineTo = await SendOnlineToAllPairedUsers(ownIdent).ConfigureAwait(false); + var usersToSendOnlineTo = await SendOnlineToAllPairedUsers(UserCharaIdent).ConfigureAwait(false); return usersToSendOnlineTo.Select(e => _clientIdentService.GetCharacterIdentForUid(e)).Where(t => !string.IsNullOrEmpty(t)).Distinct(StringComparer.Ordinal).ToList(); } @@ -76,7 +72,6 @@ public partial class MareHub { _logger.LogCallInfo(); - string userid = AuthenticatedUserId; var query = from userToOther in _dbContext.ClientPairs join otherToUser in _dbContext.ClientPairs @@ -92,7 +87,7 @@ public partial class MareHub } into leftJoin from otherEntry in leftJoin.DefaultIfEmpty() where - userToOther.UserUID == userid + userToOther.UserUID == UserUID select new { userToOther.OtherUser.Alias, @@ -140,22 +135,24 @@ public partial class MareHub } } - if (hadInvalidData) throw new HubException("Invalid data provided, contact the appropriate mod creator to resolve those issues" - + Environment.NewLine + if (hadInvalidData) + { + await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Error, "One or more of your supplied mods were rejected from the server. Consult /xllog for more information.").ConfigureAwait(false); + throw new HubException("Invalid data provided, contact the appropriate mod creator to resolve those issues" + + Environment.NewLine + string.Join(Environment.NewLine, invalidGamePaths.Select(p => "Invalid Game Path: " + p)) + Environment.NewLine + string.Join(Environment.NewLine, invalidFileSwapPaths.Select(p => "Invalid FileSwap Path: " + p))); + } var allPairedUsers = await GetAllPairedUnpausedUsers().ConfigureAwait(false); var allPairedUsersDict = allPairedUsers.ToDictionary(f => f, f => _clientIdentService.GetCharacterIdentForUid(f), StringComparer.Ordinal) .Where(f => visibleCharacterIds.Contains(f.Value, StringComparer.Ordinal)); - var ownIdent = _clientIdentService.GetCharacterIdentForUid(AuthenticatedUserId); - _logger.LogCallInfo(MareHubLogger.Args(visibleCharacterIds.Count, allPairedUsersDict.Count())); - await Clients.Users(allPairedUsersDict.Select(f => f.Key)).Client_UserReceiveCharacterData(characterCache, ownIdent).ConfigureAwait(false); + await Clients.Users(allPairedUsersDict.Select(f => f.Key)).Client_UserReceiveCharacterData(characterCache, UserCharaIdent).ConfigureAwait(false); _mareMetrics.IncCounter(MetricsAPI.CounterUserPushData); _mareMetrics.IncCounter(MetricsAPI.CounterUserPushDataTo, allPairedUsersDict.Count()); @@ -168,18 +165,22 @@ public partial class MareHub // don't allow adding yourself or nothing uid = uid.Trim(); - if (string.Equals(uid, AuthenticatedUserId, StringComparison.Ordinal) || string.IsNullOrWhiteSpace(uid)) return; + if (string.Equals(uid, UserUID, StringComparison.Ordinal) || string.IsNullOrWhiteSpace(uid)) return; // grab other user, check if it exists and if a pair already exists var otherUser = await _dbContext.Users.SingleOrDefaultAsync(u => u.UID == uid || u.Alias == uid).ConfigureAwait(false); var existingEntry = await _dbContext.ClientPairs.AsNoTracking() .FirstOrDefaultAsync(p => - p.User.UID == AuthenticatedUserId && p.OtherUserUID == uid).ConfigureAwait(false); - if (otherUser == null || existingEntry != null) return; + p.User.UID == UserUID && p.OtherUserUID == uid).ConfigureAwait(false); + if (otherUser == null || existingEntry != null) + { + await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Warning, $"Cannot pair with {uid}, either already paired or UID does not exist").ConfigureAwait(false); + return; + } // grab self create new client pair and save - var user = await _dbContext.Users.SingleAsync(u => u.UID == AuthenticatedUserId).ConfigureAwait(false); + var user = await _dbContext.Users.SingleAsync(u => u.UID == UserUID).ConfigureAwait(false); _logger.LogCallInfo(MareHubLogger.Args(uid, "Success")); @@ -239,8 +240,8 @@ public partial class MareHub { _logger.LogCallInfo(MareHubLogger.Args(otherUserUid, isPaused)); - if (string.Equals(otherUserUid, AuthenticatedUserId, StringComparison.Ordinal)) return; - ClientPair pair = await _dbContext.ClientPairs.SingleOrDefaultAsync(w => w.UserUID == AuthenticatedUserId && w.OtherUserUID == otherUserUid).ConfigureAwait(false); + if (string.Equals(otherUserUid, UserUID, StringComparison.Ordinal)) return; + ClientPair pair = await _dbContext.ClientPairs.SingleOrDefaultAsync(w => w.UserUID == UserUID && w.OtherUserUID == otherUserUid).ConfigureAwait(false); if (pair == null) return; pair.IsPaused = isPaused; @@ -251,7 +252,7 @@ public partial class MareHub var otherEntry = OppositeEntry(otherUserUid); - await Clients.User(AuthenticatedUserId).Client_UserUpdateClientPairs( + await Clients.User(UserUID).Client_UserUpdateClientPairs( new ClientPairDto() { OtherUID = otherUserUid, @@ -263,19 +264,18 @@ public partial class MareHub { await Clients.User(otherUserUid).Client_UserUpdateClientPairs(new ClientPairDto() { - OtherUID = AuthenticatedUserId, + OtherUID = UserUID, IsPaused = otherEntry.IsPaused, IsPausedFromOthers = isPaused, IsSynced = true }).ConfigureAwait(false); - var selfCharaIdent = _clientIdentService.GetCharacterIdentForUid(AuthenticatedUserId); var otherCharaIdent = _clientIdentService.GetCharacterIdentForUid(pair.OtherUserUID); - if (selfCharaIdent == null || otherCharaIdent == null || otherEntry.IsPaused) return; + if (UserCharaIdent == null || otherCharaIdent == null || otherEntry.IsPaused) return; - await Clients.User(AuthenticatedUserId).Client_UserChangePairedPlayer(otherCharaIdent, !isPaused).ConfigureAwait(false); - await Clients.User(otherUserUid).Client_UserChangePairedPlayer(selfCharaIdent, !isPaused).ConfigureAwait(false); + await Clients.User(UserUID).Client_UserChangePairedPlayer(otherCharaIdent, !isPaused).ConfigureAwait(false); + await Clients.User(otherUserUid).Client_UserChangePairedPlayer(UserCharaIdent, !isPaused).ConfigureAwait(false); } } @@ -284,11 +284,11 @@ public partial class MareHub { _logger.LogCallInfo(MareHubLogger.Args(otherUserUid)); - if (string.Equals(otherUserUid, AuthenticatedUserId, StringComparison.Ordinal)) return; + if (string.Equals(otherUserUid, UserUID, StringComparison.Ordinal)) return; // check if client pair even exists ClientPair callerPair = - await _dbContext.ClientPairs.SingleOrDefaultAsync(w => w.UserUID == AuthenticatedUserId && w.OtherUserUID == otherUserUid).ConfigureAwait(false); + await _dbContext.ClientPairs.SingleOrDefaultAsync(w => w.UserUID == UserUID && w.OtherUserUID == otherUserUid).ConfigureAwait(false); bool callerHadPaused = callerPair.IsPaused; if (callerPair == null) return; @@ -298,7 +298,7 @@ public partial class MareHub _logger.LogCallInfo(MareHubLogger.Args(otherUserUid, "Success")); - await Clients.User(AuthenticatedUserId) + await Clients.User(UserUID) .Client_UserUpdateClientPairs(new ClientPairDto() { OtherUID = otherUserUid, @@ -317,7 +317,7 @@ public partial class MareHub await Clients.User(otherUserUid).Client_UserUpdateClientPairs( new ClientPairDto() { - OtherUID = AuthenticatedUserId, + OtherUID = UserUID, IsPausedFromOthers = false, IsSynced = false }).ConfigureAwait(false); @@ -336,20 +336,18 @@ public partial class MareHub // if neither user had paused each other and either is not in an unpaused group with each other, change state to offline if (!callerHadPaused && !otherHadPaused && isPausedInGroup) { - var userIdent = _clientIdentService.GetCharacterIdentForUid(AuthenticatedUserId); - await Clients.User(AuthenticatedUserId).Client_UserChangePairedPlayer(otherIdent, false).ConfigureAwait(false); - await Clients.User(otherUserUid).Client_UserChangePairedPlayer(userIdent, false).ConfigureAwait(false); + await Clients.User(UserUID).Client_UserChangePairedPlayer(otherIdent, false).ConfigureAwait(false); + await Clients.User(otherUserUid).Client_UserChangePairedPlayer(UserCharaIdent, false).ConfigureAwait(false); } // if the caller had paused other but not the other has paused the caller and they are in an unpaused group together, change state to online if (callerHadPaused && !otherHadPaused && !isPausedInGroup) { - var userIdent = _clientIdentService.GetCharacterIdentForUid(AuthenticatedUserId); - await Clients.User(AuthenticatedUserId).Client_UserChangePairedPlayer(otherIdent, true).ConfigureAwait(false); - await Clients.User(otherUserUid).Client_UserChangePairedPlayer(userIdent, true).ConfigureAwait(false); + await Clients.User(UserUID).Client_UserChangePairedPlayer(otherIdent, true).ConfigureAwait(false); + await Clients.User(otherUserUid).Client_UserChangePairedPlayer(UserCharaIdent, true).ConfigureAwait(false); } } private ClientPair OppositeEntry(string otherUID) => - _dbContext.ClientPairs.AsNoTracking().SingleOrDefault(w => w.User.UID == otherUID && w.OtherUser.UID == AuthenticatedUserId); + _dbContext.ClientPairs.AsNoTracking().SingleOrDefault(w => w.User.UID == otherUID && w.OtherUser.UID == UserUID); } diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs index c24f0ba..9900ea8 100644 --- a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs @@ -1,5 +1,4 @@ -using System.Security.Claims; -using MareSynchronos.API; +using MareSynchronos.API; using MareSynchronosServer.Services; using MareSynchronosServer.Utils; using MareSynchronosShared; @@ -10,7 +9,6 @@ using MareSynchronosShared.Services; using MareSynchronosShared.Utils; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.SignalR; -using Microsoft.EntityFrameworkCore; namespace MareSynchronosServer.Hubs; @@ -51,57 +49,40 @@ public partial class MareHub : Hub, IMareHub _dbContext = mareDbContext; } - [Authorize(Policy = "Authenticated")] - public async Task Heartbeat(string characterIdentification) + [Authorize(Policy = "Identified")] + public async Task GetConnectionDto() { + _logger.LogCallInfo(); + _mareMetrics.IncCounter(MetricsAPI.CounterInitializedConnections); - var userId = Context.User!.Claims.SingleOrDefault(c => string.Equals(c.Type, ClaimTypes.NameIdentifier, StringComparison.Ordinal))?.Value; - - _logger.LogCallInfo(MareHubLogger.Args(characterIdentification)); - await Clients.Caller.Client_UpdateSystemInfo(_systemInfoService.SystemInfoDto).ConfigureAwait(false); - var isBanned = await _dbContext.BannedUsers.AsNoTracking().AnyAsync(u => u.CharacterIdentification == characterIdentification).ConfigureAwait(false); + var dbUser = _dbContext.Users.SingleOrDefault(f => f.UID == UserUID); + dbUser.LastLoggedIn = DateTime.UtcNow; + await _dbContext.SaveChangesAsync().ConfigureAwait(false); - if (!string.IsNullOrEmpty(userId) && !isBanned && !string.IsNullOrEmpty(characterIdentification)) + await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Information, "Welcome to Mare Synchronos \"" + _shardName + "\", Current Online Users: " + _systemInfoService.SystemInfoDto.OnlineUsers).ConfigureAwait(false); + + return new ConnectionDto() { - var user = (await _dbContext.Users.SingleAsync(u => u.UID == userId).ConfigureAwait(false)); - var existingIdent = _clientIdentService.GetCharacterIdentForUid(userId); - if (!string.IsNullOrEmpty(existingIdent) && !string.Equals(characterIdentification, existingIdent, StringComparison.Ordinal)) + ServerVersion = IMareHub.ApiVersion, + UID = string.IsNullOrEmpty(dbUser.Alias) ? dbUser.UID : dbUser.Alias, + IsAdmin = dbUser.IsAdmin, + IsModerator = dbUser.IsModerator, + ServerInfo = new ServerInfoDto() { - _logger.LogCallWarning(MareHubLogger.Args(characterIdentification, "Failure", "LoggedIn")); - - return new ConnectionDto() - { - ServerVersion = IMareHub.ApiVersion - }; + MaxGroupsCreatedByUser = _maxExistingGroupsByUser, + ShardName = _shardName, + MaxGroupsJoinedByUser = _maxJoinedGroupsByUser, + MaxGroupUserCount = _maxGroupUserCount } + }; + } - user.LastLoggedIn = DateTime.UtcNow; - _clientIdentService.MarkUserOnline(user.UID, characterIdentification); - await _dbContext.SaveChangesAsync().ConfigureAwait(false); - - _logger.LogCallInfo(MareHubLogger.Args(characterIdentification, "Success")); - - return new ConnectionDto - { - ServerVersion = IMareHub.ApiVersion, - UID = string.IsNullOrEmpty(user.Alias) ? user.UID : user.Alias, - IsModerator = user.IsModerator, - IsAdmin = user.IsAdmin, - ServerInfo = new ServerInfoDto() - { - MaxGroupsCreatedByUser = _maxExistingGroupsByUser, - ShardName = _shardName, - MaxGroupsJoinedByUser = _maxJoinedGroupsByUser, - MaxGroupUserCount = _maxGroupUserCount - } - }; - } - - _logger.LogCallWarning(MareHubLogger.Args(characterIdentification, "Failure")); - + [Authorize(Policy = "Authenticated")] + public async Task Heartbeat(string characterIdentification) + { return new ConnectionDto() { ServerVersion = IMareHub.ApiVersion @@ -109,21 +90,31 @@ public partial class MareHub : Hub, IMareHub } [Authorize(Policy = "Authenticated")] - public Task CheckClientHealth() + public async Task CheckClientHealth() { - var needsReconnect = !_clientIdentService.IsOnCurrentServer(AuthenticatedUserId); + var needsReconnect = !_clientIdentService.IsOnCurrentServer(UserUID); if (needsReconnect) { + await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Warning, "Internal server state corruption detected, reconnecting you automatically to fix the issue.").ConfigureAwait(false); _logger.LogCallWarning(MareHubLogger.Args(needsReconnect)); } - return Task.FromResult(needsReconnect); + + return needsReconnect; } [Authorize(Policy = "Authenticated")] public override async Task OnConnectedAsync() { - _logger.LogCallInfo(MareHubLogger.Args(_contextAccessor.GetIpAddress())); _mareMetrics.IncGauge(MetricsAPI.GaugeConnections); + + try + { + _logger.LogCallInfo(MareHubLogger.Args(_contextAccessor.GetIpAddress(), UserCharaIdent)); + + _clientIdentService.MarkUserOnline(UserUID, UserCharaIdent); + } + catch { } + await base.OnConnectedAsync().ConfigureAwait(false); } @@ -132,19 +123,18 @@ public partial class MareHub : Hub, IMareHub { _mareMetrics.DecGauge(MetricsAPI.GaugeConnections); - var userCharaIdent = _clientIdentService.GetCharacterIdentForUid(AuthenticatedUserId); - - if (!string.IsNullOrEmpty(userCharaIdent)) + try { - _logger.LogCallInfo(); - _clientIdentService.MarkUserOffline(AuthenticatedUserId); + _logger.LogCallInfo(MareHubLogger.Args(_contextAccessor.GetIpAddress(), UserCharaIdent)); - await SendOfflineToAllPairedUsers(userCharaIdent).ConfigureAwait(false); + _clientIdentService.MarkUserOffline(UserUID); - _dbContext.RemoveRange(_dbContext.Files.Where(f => !f.Uploaded && f.UploaderUID == AuthenticatedUserId)); + await SendOfflineToAllPairedUsers(UserCharaIdent).ConfigureAwait(false); + _dbContext.RemoveRange(_dbContext.Files.Where(f => !f.Uploaded && f.UploaderUID == UserUID)); await _dbContext.SaveChangesAsync().ConfigureAwait(false); } + catch { } await base.OnDisconnectedAsync(exception).ConfigureAwait(false); } diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/SignalRLimitFilter.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/SignalRLimitFilter.cs index 0b872a8..1c8fa0c 100644 --- a/MareSynchronosServer/MareSynchronosServer/Hubs/SignalRLimitFilter.cs +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/SignalRLimitFilter.cs @@ -1,5 +1,4 @@ -using System.Security.Claims; -using AspNetCoreRateLimit; +using AspNetCoreRateLimit; using MareSynchronosShared; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Options; @@ -37,7 +36,7 @@ public class SignalRLimitFilter : IHubFilter var counter = await _processor.ProcessRequestAsync(client, rule).ConfigureAwait(false); if (counter.Count > rule.Limit) { - var authUserId = invocationContext.Context.User.Claims?.SingleOrDefault(c => string.Equals(c.Type, ClaimTypes.NameIdentifier, StringComparison.Ordinal))?.Value ?? "Unknown"; + var authUserId = invocationContext.Context.User.Claims?.SingleOrDefault(c => string.Equals(c.Type, MareClaimTypes.Uid, StringComparison.Ordinal))?.Value ?? "Unknown"; var retry = counter.Timestamp.RetryAfterFrom(rule); logger.LogWarning("Method rate limit triggered from {ip}/{authUserId}: {method}", ip, authUserId, invocationContext.HubMethodName); throw new HubException($"call limit {retry}"); diff --git a/MareSynchronosServer/MareSynchronosServer/RequirementHandlers/UserRequirementHandler.cs b/MareSynchronosServer/MareSynchronosServer/RequirementHandlers/UserRequirementHandler.cs index 4fc2443..77937aa 100644 --- a/MareSynchronosServer/MareSynchronosServer/RequirementHandlers/UserRequirementHandler.cs +++ b/MareSynchronosServer/MareSynchronosServer/RequirementHandlers/UserRequirementHandler.cs @@ -1,9 +1,9 @@ -using System.Security.Claims; -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.SignalR; using MareSynchronosShared.Data; using Microsoft.EntityFrameworkCore; using MareSynchronosServer.Services; +using MareSynchronosServer.Hubs; namespace MareSynchronosServer.RequirementHandlers; @@ -22,7 +22,7 @@ public class UserRequirementHandler : AuthorizationHandler string.Equals(g.Type, ClaimTypes.NameIdentifier, StringComparison.Ordinal))?.Value; + var uid = context.User.Claims.SingleOrDefault(g => string.Equals(g.Type, MareClaimTypes.Uid, StringComparison.Ordinal))?.Value; if (uid == null) context.Fail(); diff --git a/MareSynchronosServer/MareSynchronosServer/Services/ClientMessageService.cs b/MareSynchronosServer/MareSynchronosServer/Services/ClientMessageService.cs new file mode 100644 index 0000000..8b8acf8 --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/Services/ClientMessageService.cs @@ -0,0 +1,46 @@ +using Grpc.Core; +using MareSynchronos.API; +using MareSynchronosServer.Hubs; +using MareSynchronosShared.Protos; +using Microsoft.AspNetCore.SignalR; +using static MareSynchronosShared.Protos.ClientMessageService; + +namespace MareSynchronosServer.Services; + +public class GrpcClientMessageService : ClientMessageServiceBase +{ + private readonly ILogger _logger; + private readonly IHubContext _hubContext; + + public GrpcClientMessageService(ILogger logger, IHubContext hubContext) + { + _logger = logger; + _hubContext = hubContext; + } + + public override async Task SendClientMessage(ClientMessage request, ServerCallContext context) + { + bool hasUid = !string.IsNullOrEmpty(request.Uid); + + var severity = request.Type switch + { + MessageType.Info => MessageSeverity.Information, + MessageType.Warning => MessageSeverity.Warning, + MessageType.Error => MessageSeverity.Error, + _ => MessageSeverity.Information, + }; + + if (!hasUid) + { + _logger.LogInformation("Sending Message of severity {severity} to all online users: {message}", severity, request.Message); + await _hubContext.Clients.All.Client_ReceiveServerMessage(severity, request.Message).ConfigureAwait(false); + } + else + { + _logger.LogInformation("Sending Message of severity {severity} to user {uid}: {message}", severity, request.Uid, request.Message); + await _hubContext.Clients.User(request.Uid).Client_ReceiveServerMessage(severity, request.Message).ConfigureAwait(false); + } + + return new Empty(); + } +} diff --git a/MareSynchronosServer/MareSynchronosServer/Services/GrpcClientIdentificationService.cs b/MareSynchronosServer/MareSynchronosServer/Services/GrpcClientIdentificationService.cs index 33a1778..0164223 100644 --- a/MareSynchronosServer/MareSynchronosServer/Services/GrpcClientIdentificationService.cs +++ b/MareSynchronosServer/MareSynchronosServer/Services/GrpcClientIdentificationService.cs @@ -94,9 +94,10 @@ public class GrpcClientIdentificationService : GrpcBaseService, IClientIdentific public void MarkUserOffline(string uid) { + _metrics.SetGaugeTo(MetricsAPI.GaugeAuthorizedConnections, OnlineClients.Count); + if (OnlineClients.TryRemove(uid, out var uidWithIdent)) { - _metrics.SetGaugeTo(MetricsAPI.GaugeAuthorizedConnections, OnlineClients.Count); _identChangeQueue.Enqueue(new IdentChange() { IsOnline = false, @@ -172,6 +173,7 @@ public class GrpcClientIdentificationService : GrpcBaseService, IClientIdentific _logger.LogInformation("Starting Receive Online Client Data stream"); await foreach (var cur in stream.ResponseStream.ReadAllAsync(cts).ConfigureAwait(false)) { + OnlineClients.Remove(cur.UidWithIdent.Uid.Uid, out _); if (cur.IsOnline) { RemoteCachedIdents[cur.UidWithIdent.Uid.Uid] = cur.UidWithIdent; diff --git a/MareSynchronosServer/MareSynchronosServer/Services/SystemInfoService.cs b/MareSynchronosServer/MareSynchronosServer/Services/SystemInfoService.cs index e249fcc..0212551 100644 --- a/MareSynchronosServer/MareSynchronosServer/Services/SystemInfoService.cs +++ b/MareSynchronosServer/MareSynchronosServer/Services/SystemInfoService.cs @@ -47,14 +47,14 @@ public class SystemInfoService : IHostedService, IDisposable _mareMetrics.SetGaugeTo(MetricsAPI.GaugeAvailableWorkerThreads, workerThreads); _mareMetrics.SetGaugeTo(MetricsAPI.GaugeAvailableIOWorkerThreads, ioThreads); + var onlineUsers = (int)_clientIdentService.GetOnlineUsers().Result; + SystemInfoDto = new SystemInfoDto() + { + OnlineUsers = onlineUsers, + }; + if (_config.IsMain) { - var onlineUsers = (int)_clientIdentService.GetOnlineUsers().Result; - SystemInfoDto = new SystemInfoDto() - { - OnlineUsers = onlineUsers, - }; - _logger.LogInformation("Sending System Info, Online Users: {onlineUsers}", onlineUsers); _hubContext.Clients.All.Client_UpdateSystemInfo(SystemInfoDto); diff --git a/MareSynchronosServer/MareSynchronosServer/Startup.cs b/MareSynchronosServer/MareSynchronosServer/Startup.cs index 6abc6dd..f50d0ff 100644 --- a/MareSynchronosServer/MareSynchronosServer/Startup.cs +++ b/MareSynchronosServer/MareSynchronosServer/Startup.cs @@ -5,7 +5,6 @@ using Microsoft.AspNetCore.Http.Connections; using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.Authorization; using AspNetCoreRateLimit; -using MareSynchronosShared.Authentication; using MareSynchronosShared.Data; using MareSynchronosShared.Protos; using Grpc.Net.Client.Configuration; @@ -22,6 +21,7 @@ using Grpc.Net.ClientFactory; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using System.Text; +using MareSynchronosServer.Authentication; namespace MareSynchronosServer; @@ -79,7 +79,7 @@ public class Startup services.AddSingleton(); services.AddHostedService(provider => provider.GetService()); // configure services based on main server status - ConfigureIdentityServices(services, mareConfig, isMainServer); + ConfigureServicesBasedOnShardType(services, mareConfig, isMainServer); if (isMainServer) { @@ -210,7 +210,7 @@ public class Startup })); } - private static void ConfigureIdentityServices(IServiceCollection services, IConfigurationSection mareConfig, bool isMainServer) + private static void ConfigureServicesBasedOnShardType(IServiceCollection services, IConfigurationSection mareConfig, bool isMainServer) { if (!isMainServer) { @@ -325,6 +325,7 @@ public class Startup { endpoints.MapGrpcService().AllowAnonymous(); endpoints.MapGrpcService>().AllowAnonymous(); + endpoints.MapGrpcService().AllowAnonymous(); } endpoints.MapHealthChecks("/health").AllowAnonymous(); diff --git a/MareSynchronosServer/MareSynchronosServer/Utils/IdBasedUserIdProvider.cs b/MareSynchronosServer/MareSynchronosServer/Utils/IdBasedUserIdProvider.cs index 17b65dd..0c93b1a 100644 --- a/MareSynchronosServer/MareSynchronosServer/Utils/IdBasedUserIdProvider.cs +++ b/MareSynchronosServer/MareSynchronosServer/Utils/IdBasedUserIdProvider.cs @@ -1,4 +1,4 @@ -using System.Security.Claims; +using MareSynchronosServer.Hubs; using Microsoft.AspNetCore.SignalR; namespace MareSynchronosServer.Utils; @@ -7,6 +7,6 @@ public class IdBasedUserIdProvider : IUserIdProvider { public string GetUserId(HubConnectionContext context) { - return context.User!.Claims.SingleOrDefault(c => string.Equals(c.Type, ClaimTypes.NameIdentifier, StringComparison.Ordinal))?.Value; + return context.User!.Claims.SingleOrDefault(c => string.Equals(c.Type, MareClaimTypes.Uid, StringComparison.Ordinal))?.Value; } } diff --git a/MareSynchronosServer/MareSynchronosServer/Utils/MareHubLogger.cs b/MareSynchronosServer/MareSynchronosServer/Utils/MareHubLogger.cs index eaddcca..91a95e2 100644 --- a/MareSynchronosServer/MareSynchronosServer/Utils/MareHubLogger.cs +++ b/MareSynchronosServer/MareSynchronosServer/Utils/MareHubLogger.cs @@ -22,12 +22,12 @@ public class MareHubLogger public void LogCallInfo(object[] args = null, [CallerMemberName] string methodName = "") { string formattedArgs = args != null && args.Length != 0 ? "|" + string.Join(":", args) : string.Empty; - _logger.LogInformation("{uid}:{method}{args}", _hub.AuthenticatedUserId, methodName, formattedArgs); + _logger.LogInformation("{uid}:{method}{args}", _hub.UserUID, methodName, formattedArgs); } public void LogCallWarning(object[] args = null, [CallerMemberName] string methodName = "") { string formattedArgs = args != null && args.Length != 0 ? "|" + string.Join(":", args) : string.Empty; - _logger.LogWarning("{uid}:{method}{args}", _hub.AuthenticatedUserId, methodName, formattedArgs); + _logger.LogWarning("{uid}:{method}{args}", _hub.UserUID, methodName, formattedArgs); } } diff --git a/MareSynchronosServer/MareSynchronosServices/Discord/MareModule.cs b/MareSynchronosServer/MareSynchronosServices/Discord/MareModule.cs index a2c7dd7..ac9a504 100644 --- a/MareSynchronosServer/MareSynchronosServices/Discord/MareModule.cs +++ b/MareSynchronosServer/MareSynchronosServices/Discord/MareModule.cs @@ -6,11 +6,11 @@ using Microsoft.EntityFrameworkCore; using Discord.WebSocket; using Prometheus; using MareSynchronosShared.Models; -using MareSynchronosShared.Metrics; using MareSynchronosShared.Utils; using MareSynchronosShared.Services; using static MareSynchronosShared.Protos.IdentificationService; -using static System.Formats.Asn1.AsnWriter; +using Grpc.Net.ClientFactory; +using MareSynchronosShared.Protos; namespace MareSynchronosServices.Discord; @@ -30,23 +30,26 @@ public class MareModule : InteractionModuleBase private readonly DiscordBotServices _botServices; private readonly IdentificationServiceClient _identificationServiceClient; private readonly IConfigurationService _mareClientConfigurationService; + private readonly GrpcClientFactory _grpcClientFactory; private Random random = new(); public MareModule(ILogger logger, IServiceProvider services, DiscordBotServices botServices, - IdentificationServiceClient identificationServiceClient, IConfigurationService mareClientConfigurationService) + IdentificationServiceClient identificationServiceClient, IConfigurationService mareClientConfigurationService, + GrpcClientFactory grpcClientFactory) { _logger = logger; _services = services; _botServices = botServices; _identificationServiceClient = identificationServiceClient; _mareClientConfigurationService = mareClientConfigurationService; + _grpcClientFactory = grpcClientFactory; } [SlashCommand("register", "Starts the registration process for the Mare Synchronos server of this Discord")] public async Task Register([Summary("overwrite", "Overwrites your old account")] bool overwrite = false) { _logger.LogInformation("SlashCommand:{userId}:{Method}:{params}", - Context.Client.CurrentUser.Id, nameof(Register), + Context.Interaction.User.Id, nameof(Register), string.Join(",", new[] { $"{nameof(overwrite)}:{overwrite}" })); await TryRespondAsync(async () => @@ -64,7 +67,7 @@ public class MareModule : InteractionModuleBase public async Task SetVanityUid([Summary("vanity_uid", "Desired Vanity UID")] string vanityUid) { _logger.LogInformation("SlashCommand:{userId}:{Method}:{params}", - Context.Client.CurrentUser.Id, nameof(SetVanityUid), + Context.Interaction.User.Id, nameof(SetVanityUid), string.Join(",", new[] { $"{nameof(vanityUid)}:{vanityUid}" })); await TryRespondAsync(async () => @@ -83,7 +86,7 @@ public class MareModule : InteractionModuleBase [Summary("vanity_syncshell_id", "Desired Vanity Syncshell ID")] string vanityId) { _logger.LogInformation("SlashCommand:{userId}:{Method}:{params}", - Context.Client.CurrentUser.Id, nameof(SetSyncshellVanityId), + Context.Interaction.User.Id, nameof(SetSyncshellVanityId), string.Join(",", new[] { $"{nameof(syncshellId)}:{syncshellId}", $"{nameof(vanityId)}:{vanityId}" })); await TryRespondAsync(async () => @@ -100,7 +103,7 @@ public class MareModule : InteractionModuleBase public async Task Verify() { _logger.LogInformation("SlashCommand:{userId}:{Method}", - Context.Client.CurrentUser.Id, nameof(Verify)); + Context.Interaction.User.Id, nameof(Verify)); await TryRespondAsync(async () => { EmbedBuilder eb = new(); @@ -128,7 +131,7 @@ public class MareModule : InteractionModuleBase public async Task VerifyRelink() { _logger.LogInformation("SlashCommand:{userId}:{Method}", - Context.Client.CurrentUser.Id, nameof(VerifyRelink)); + Context.Interaction.User.Id, nameof(VerifyRelink)); await TryRespondAsync(async () => { EmbedBuilder eb = new(); @@ -156,7 +159,7 @@ public class MareModule : InteractionModuleBase public async Task Recover() { _logger.LogInformation("SlashCommand:{userId}:{Method}", - Context.Client.CurrentUser.Id, nameof(Recover)); + Context.Interaction.User.Id, nameof(Recover)); await RespondWithModalAsync("recover_modal").ConfigureAwait(false); } @@ -166,7 +169,7 @@ public class MareModule : InteractionModuleBase [Summary("uid", "ADMIN ONLY: UID to check for")] string? uid = null) { _logger.LogInformation("SlashCommand:{userId}:{Method}", - Context.Client.CurrentUser.Id, nameof(UserInfo)); + Context.Interaction.User.Id, nameof(UserInfo)); await TryRespondAsync(async () => { @@ -182,7 +185,7 @@ public class MareModule : InteractionModuleBase public async Task Relink() { _logger.LogInformation("SlashCommand:{userId}:{Method}", - Context.Client.CurrentUser.Id, nameof(Relink)); + Context.Interaction.User.Id, nameof(Relink)); await RespondWithModalAsync("relink_modal").ConfigureAwait(false); } @@ -190,7 +193,7 @@ public class MareModule : InteractionModuleBase public async Task UserAdd([Summary("desired_uid", "Desired UID")] string desiredUid) { _logger.LogInformation("SlashCommand:{userId}:{Method}:{params}", - Context.Client.CurrentUser.Id, nameof(UserAdd), + Context.Interaction.User.Id, nameof(UserAdd), string.Join(",", new[] { $"{nameof(desiredUid)}:{desiredUid}" })); await TryRespondAsync(async () => @@ -201,11 +204,51 @@ public class MareModule : InteractionModuleBase }); } + [SlashCommand("message", "ADMIN ONLY: sends a message to clients")] + public async Task SendMessageToClients([Summary("message", "Message to send")] string message, + [Summary("severity", "Severity of the message")] MareSynchronosShared.Protos.MessageType messageType = MareSynchronosShared.Protos.MessageType.Info, + [Summary("uid", "User ID to the person to send the message to")] string? uid = null) + { + _logger.LogInformation("SlashCommand:{userId}:{Method}:{message}:{type}:{uid}", Context.Interaction.User.Id, nameof(SendMessageToClients), message, messageType, uid); + + using var scope = _services.CreateScope(); + using var db = scope.ServiceProvider.GetService(); + + if (!(await db.LodeStoneAuth.Include(u => u.User).SingleOrDefaultAsync(a => a.DiscordId == Context.Interaction.User.Id))?.User?.IsAdmin ?? true) + { + await RespondAsync("No permission", ephemeral: true).ConfigureAwait(false); + return; + } + + if (!string.IsNullOrEmpty(uid) && !await db.Users.AnyAsync(u => u.UID == uid)) + { + await RespondAsync("Specified UID does not exist", ephemeral: true).ConfigureAwait(false); + return; + } + + try + { + var client = _grpcClientFactory.CreateClient("MessageClient"); + await client.SendClientMessageAsync(new ClientMessage() + { + Message = message, + Type = messageType, + Uid = uid ?? string.Empty + }); + + await RespondAsync("Message sent", ephemeral: true).ConfigureAwait(false); + } + catch (Exception ex) + { + await RespondAsync("Failed to send message: " + ex.ToString(), ephemeral: true).ConfigureAwait(false); + } + } + [ModalInteraction("recover_modal")] public async Task RecoverModal(LodestoneModal modal) { _logger.LogInformation("Modal:{userId}:{Method}", - Context.Client.CurrentUser.Id, nameof(RecoverModal)); + Context.Interaction.User.Id, nameof(RecoverModal)); await TryRespondAsync(async () => { @@ -218,7 +261,7 @@ public class MareModule : InteractionModuleBase public async Task RegisterModal(LodestoneModal modal) { _logger.LogInformation("Modal:{userId}:{Method}", - Context.Client.CurrentUser.Id, nameof(RegisterModal)); + Context.Interaction.User.Id, nameof(RegisterModal)); await TryRespondAsync(async () => { @@ -231,7 +274,7 @@ public class MareModule : InteractionModuleBase public async Task RelinkModal(LodestoneModal modal) { _logger.LogInformation("Modal:{userId}:{Method}", - Context.Client.CurrentUser.Id, nameof(RelinkModal)); + Context.Interaction.User.Id, nameof(RelinkModal)); await TryRespondAsync(async () => { diff --git a/MareSynchronosServer/MareSynchronosServices/Startup.cs b/MareSynchronosServer/MareSynchronosServices/Startup.cs index 1ecd417..3fb089d 100644 --- a/MareSynchronosServer/MareSynchronosServices/Startup.cs +++ b/MareSynchronosServer/MareSynchronosServices/Startup.cs @@ -68,6 +68,18 @@ public class Startup }; }); + services.AddGrpcClient("MessageClient", c => + { + c.Address = new Uri(mareConfig.GetValue(nameof(ServicesConfiguration.MainServerGrpcAddress))); + }).ConfigureChannel(c => + { + c.ServiceConfig = new ServiceConfig { MethodConfigs = { noRetryConfig } }; + c.HttpHandler = new SocketsHttpHandler() + { + EnableMultipleHttp2Connections = true + }; + }); + services.Configure(Configuration.GetRequiredSection("MareSynchronos")); services.Configure(Configuration.GetRequiredSection("MareSynchronos")); services.Configure(Configuration.GetRequiredSection("MareSynchronos")); diff --git a/MareSynchronosServer/MareSynchronosShared/Authentication/SecretKeyAuthReply.cs b/MareSynchronosServer/MareSynchronosShared/Authentication/SecretKeyAuthReply.cs deleted file mode 100644 index bfe3995..0000000 --- a/MareSynchronosServer/MareSynchronosShared/Authentication/SecretKeyAuthReply.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace MareSynchronosShared.Authentication; - -public record SecretKeyAuthReply(bool Success, string? Uid); diff --git a/MareSynchronosServer/MareSynchronosShared/Protos/mareservices.proto b/MareSynchronosServer/MareSynchronosShared/Protos/mareservices.proto index 46fa791..8c9e8cf 100644 --- a/MareSynchronosServer/MareSynchronosShared/Protos/mareservices.proto +++ b/MareSynchronosServer/MareSynchronosShared/Protos/mareservices.proto @@ -23,6 +23,22 @@ service ConfigurationService { rpc GetConfigurationEntry (KeyMessage) returns (ValueMessage); } +service ClientMessageService { + rpc SendClientMessage (ClientMessage) returns (Empty); +} + +message ClientMessage { + MessageType type = 1; + string message = 2; + string uid = 3; +} + +enum MessageType { + INFO = 0; + WARNING = 1; + ERROR = 2; +} + message KeyMessage { string key = 1; string default = 2; diff --git a/MareSynchronosServer/MareSynchronosStaticFilesServer/Startup.cs b/MareSynchronosServer/MareSynchronosStaticFilesServer/Startup.cs index 120b589..14d2d48 100644 --- a/MareSynchronosServer/MareSynchronosStaticFilesServer/Startup.cs +++ b/MareSynchronosServer/MareSynchronosStaticFilesServer/Startup.cs @@ -1,12 +1,10 @@ using Grpc.Net.Client.Configuration; using Grpc.Net.ClientFactory; -using MareSynchronosShared.Authentication; using MareSynchronosShared.Data; using MareSynchronosShared.Metrics; using MareSynchronosShared.Protos; using MareSynchronosShared.Services; using MareSynchronosShared.Utils; -using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.EntityFrameworkCore; @@ -45,10 +43,6 @@ public class Startup services.AddSingleton(m => new MareMetrics(m.GetService>(), new List { - MetricsAPI.CounterAuthenticationCacheHits, - MetricsAPI.CounterAuthenticationFailures, - MetricsAPI.CounterAuthenticationRequests, - MetricsAPI.CounterAuthenticationSuccesses }, new List { MetricsAPI.GaugeFilesTotalSize, @@ -64,7 +58,6 @@ public class Startup services.AddHostedService(m => m.GetService()); services.AddHostedService(); - services.AddSingleton(); services.AddDbContextPool(options => { options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection"), builder =>