update to API 5, consolidate hubs into one
This commit is contained in:
		
							
								
								
									
										299
									
								
								MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										299
									
								
								MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,299 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Security.Cryptography; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| using MareSynchronos.API; | ||||
| using MareSynchronosServer.Authentication; | ||||
| using MareSynchronosServer.Models; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Microsoft.AspNetCore.SignalR; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using Microsoft.Extensions.Logging; | ||||
|  | ||||
| namespace MareSynchronosServer.Hubs | ||||
| { | ||||
|     public partial class MareHub | ||||
|     { | ||||
|         [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)] | ||||
|         [HubMethodName(Api.SendUserDeleteAccount)] | ||||
|         public async Task DeleteAccount() | ||||
|         { | ||||
|             _logger.LogInformation("User " + AuthenticatedUserId + " deleted their account"); | ||||
|  | ||||
|             string userid = AuthenticatedUserId; | ||||
|             var userEntry = await _dbContext.Users.SingleAsync(u => u.UID == userid); | ||||
|             var ownPairData = _dbContext.ClientPairs.Where(u => u.User.UID == userid); | ||||
|             _dbContext.RemoveRange(ownPairData); | ||||
|             await _dbContext.SaveChangesAsync(); | ||||
|             var otherPairData = _dbContext.ClientPairs.Include(u => u.User).Where(u => u.OtherUser.UID == userid); | ||||
|             foreach (var pair in otherPairData) | ||||
|             { | ||||
|                 await Clients.User(pair.User.UID) | ||||
|                     .SendAsync(Api.OnUserUpdateClientPairs, new ClientPairDto() | ||||
|                     { | ||||
|                         OtherUID = userid, | ||||
|                         IsRemoved = true | ||||
|                     }, userEntry.CharacterIdentification); | ||||
|             } | ||||
|  | ||||
|             _dbContext.RemoveRange(otherPairData); | ||||
|             _dbContext.Remove(userEntry); | ||||
|             await _dbContext.SaveChangesAsync(); | ||||
|         } | ||||
|  | ||||
|         [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)] | ||||
|         [HubMethodName(Api.InvokeUserGetOnlineCharacters)] | ||||
|         public async Task<List<string>> GetOnlineCharacters() | ||||
|         { | ||||
|             _logger.LogInformation("User " + AuthenticatedUserId + " requested online characters"); | ||||
|  | ||||
|             var ownUser = await GetAuthenticatedUserUntrackedAsync(); | ||||
|  | ||||
|             var otherUsers = await _dbContext.ClientPairs.AsNoTracking() | ||||
|             .Include(u => u.User) | ||||
|             .Include(u => u.OtherUser) | ||||
|             .Where(w => w.User.UID == ownUser.UID && !w.IsPaused) | ||||
|             .Where(w => !string.IsNullOrEmpty(w.OtherUser.CharacterIdentification)) | ||||
|             .Select(e => e.OtherUser).ToListAsync(); | ||||
|             var otherEntries = await _dbContext.ClientPairs.AsNoTracking() | ||||
|                 .Include(u => u.User) | ||||
|                 .Where(u => otherUsers.Any(e => e == u.User) && u.OtherUser == ownUser && !u.IsPaused).ToListAsync(); | ||||
|  | ||||
|             await Clients.Users(otherEntries.Select(e => e.User.UID)).SendAsync(Api.OnUserAddOnlinePairedPlayer, ownUser.CharacterIdentification); | ||||
|             return otherEntries.Select(e => e.User.CharacterIdentification).Distinct().ToList(); | ||||
|         } | ||||
|  | ||||
|         [HubMethodName(Api.InvokeAdminGetOnlineUsers)] | ||||
|         public async Task<int> GetOnlineUsers() | ||||
|         { | ||||
|             return await _dbContext.Users.CountAsync(u => !string.IsNullOrEmpty(u.CharacterIdentification)); | ||||
|         } | ||||
|  | ||||
|         [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)] | ||||
|         [HubMethodName(Api.InvokeUserGetPairedClients)] | ||||
|         public async Task<List<ClientPairDto>> GetPairedClients() | ||||
|         { | ||||
|             string userid = AuthenticatedUserId; | ||||
|             var pairs = await _dbContext.ClientPairs.AsNoTracking() | ||||
|                 .Include(u => u.OtherUser) | ||||
|                 .Include(u => u.User) | ||||
|                 .Where(w => w.User.UID == userid) | ||||
|                 .ToListAsync(); | ||||
|             return pairs.Select(w => | ||||
|             { | ||||
|                 var otherEntry = OppositeEntry(w.OtherUser.UID); | ||||
|                 return new ClientPairDto | ||||
|                 { | ||||
|                     IsPaused = w.IsPaused, | ||||
|                     OtherUID = w.OtherUser.UID, | ||||
|                     IsSynced = otherEntry != null, | ||||
|                     IsPausedFromOthers = otherEntry?.IsPaused ?? false, | ||||
|                 }; | ||||
|             }).ToList(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|  | ||||
|         [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)] | ||||
|         [HubMethodName(Api.InvokeUserPushCharacterDataToVisibleClients)] | ||||
|         public async Task PushCharacterDataToVisibleClients(CharacterCacheDto characterCache, List<string> visibleCharacterIds) | ||||
|         { | ||||
|             _logger.LogInformation("User " + AuthenticatedUserId + " pushing character data to " + visibleCharacterIds.Count + " visible clients"); | ||||
|  | ||||
|             var user = await GetAuthenticatedUserUntrackedAsync(); | ||||
|             var senderPairedUsers = await _dbContext.ClientPairs.AsNoTracking() | ||||
|                 .Include(w => w.User) | ||||
|                 .Include(w => w.OtherUser) | ||||
|                 .Where(w => w.User.UID == user.UID && !w.IsPaused | ||||
|                     && visibleCharacterIds.Contains(w.OtherUser.CharacterIdentification)) | ||||
|                 .Select(u => u.OtherUser).ToListAsync(); | ||||
|  | ||||
|             foreach (var pairedUser in senderPairedUsers) | ||||
|             { | ||||
|                 var isPaused = (await _dbContext.ClientPairs.AsNoTracking() | ||||
|                     .FirstOrDefaultAsync(w => | ||||
|                     w.User.UID == pairedUser.UID && w.OtherUser.UID == user.UID))?.IsPaused ?? true; | ||||
|                 if (isPaused) continue; | ||||
|                 await Clients.User(pairedUser.UID).SendAsync(Api.OnUserReceiveCharacterData, characterCache, | ||||
|                     user.CharacterIdentification); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         [HubMethodName(Api.InvokeUserRegister)] | ||||
|         public async Task<string> Register() | ||||
|         { | ||||
|             using var sha256 = SHA256.Create(); | ||||
|             var user = new User(); | ||||
|  | ||||
|             var hasValidUid = false; | ||||
|             while (!hasValidUid) | ||||
|             { | ||||
|                 var uid = GenerateRandomString(10); | ||||
|                 if (_dbContext.Users.Any(u => u.UID == uid)) continue; | ||||
|                 user.UID = uid; | ||||
|                 hasValidUid = true; | ||||
|             } | ||||
|  | ||||
|             // make the first registered user on the service to admin | ||||
|             if (!await _dbContext.Users.AnyAsync()) | ||||
|             { | ||||
|                 user.IsAdmin = true; | ||||
|             } | ||||
|  | ||||
|             var computedHash = BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(GenerateRandomString(64)))).Replace("-", ""); | ||||
|             var auth = new Auth() | ||||
|             { | ||||
|                 HashedKey = BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(computedHash))) | ||||
|                     .Replace("-", ""), | ||||
|                 User = user | ||||
|             }; | ||||
|  | ||||
|             _dbContext.Users.Add(user); | ||||
|             _dbContext.Auth.Add(auth); | ||||
|  | ||||
|             _logger.LogInformation("User registered: " + user.UID); | ||||
|  | ||||
|             await _dbContext.SaveChangesAsync(); | ||||
|             return computedHash; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)] | ||||
|         [HubMethodName(Api.SendUserPairedClientAddition)] | ||||
|         public async Task SendPairedClientAddition(string uid) | ||||
|         { | ||||
|             if (uid == AuthenticatedUserId) return; | ||||
|             uid = uid.Trim(); | ||||
|             var user = await _dbContext.Users.SingleAsync(u => u.UID == AuthenticatedUserId); | ||||
|  | ||||
|             var otherUser = await _dbContext.Users | ||||
|                 .SingleOrDefaultAsync(u => u.UID == uid); | ||||
|             var existingEntry = | ||||
|                 await _dbContext.ClientPairs.AsNoTracking() | ||||
|                     .FirstOrDefaultAsync(p => | ||||
|                     p.User.UID == AuthenticatedUserId && p.OtherUser.UID == uid); | ||||
|             if (otherUser == null || existingEntry != null) return; | ||||
|             _logger.LogInformation("User " + AuthenticatedUserId + " adding " + uid + " to whitelist"); | ||||
|             ClientPair wl = new ClientPair() | ||||
|             { | ||||
|                 IsPaused = false, | ||||
|                 OtherUser = otherUser, | ||||
|                 User = user | ||||
|             }; | ||||
|             await _dbContext.ClientPairs.AddAsync(wl); | ||||
|             await _dbContext.SaveChangesAsync(); | ||||
|             var otherEntry = OppositeEntry(uid); | ||||
|             await Clients.User(user.UID) | ||||
|                 .SendAsync(Api.OnUserUpdateClientPairs, new ClientPairDto() | ||||
|                 { | ||||
|                     OtherUID = otherUser.UID, | ||||
|                     IsPaused = false, | ||||
|                     IsPausedFromOthers = otherEntry?.IsPaused ?? false, | ||||
|                     IsSynced = otherEntry != null | ||||
|                 }, string.Empty); | ||||
|             if (otherEntry != null) | ||||
|             { | ||||
|                 await Clients.User(uid).SendAsync(Api.OnUserUpdateClientPairs, | ||||
|                     new ClientPairDto() | ||||
|                     { | ||||
|                         OtherUID = user.UID, | ||||
|                         IsPaused = otherEntry.IsPaused, | ||||
|                         IsPausedFromOthers = false, | ||||
|                         IsSynced = true | ||||
|                     }, user.CharacterIdentification); | ||||
|  | ||||
|                 if (!string.IsNullOrEmpty(otherUser.CharacterIdentification)) | ||||
|                 { | ||||
|                     await Clients.User(user.UID) | ||||
|                         .SendAsync(Api.OnUserAddOnlinePairedPlayer, otherUser.CharacterIdentification); | ||||
|                     await Clients.User(otherUser.UID) | ||||
|                         .SendAsync(Api.OnUserAddOnlinePairedPlayer, user.CharacterIdentification); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)] | ||||
|         [HubMethodName(Api.SendUserPairedClientPauseChange)] | ||||
|         public async Task SendPairedClientPauseChange(string uid, bool isPaused) | ||||
|         { | ||||
|             if (uid == AuthenticatedUserId) return; | ||||
|             var user = await _dbContext.Users.AsNoTracking() | ||||
|                 .SingleAsync(u => u.UID == AuthenticatedUserId); | ||||
|             var otherUser = await _dbContext.Users.AsNoTracking() | ||||
|                 .SingleOrDefaultAsync(u => u.UID == uid); | ||||
|             if (otherUser == null) return; | ||||
|             _logger.LogInformation("User " + AuthenticatedUserId + " changed pause status with " + uid + " to " + isPaused); | ||||
|             ClientPair wl = | ||||
|                 await _dbContext.ClientPairs.SingleOrDefaultAsync(w => w.User == user && w.OtherUser == otherUser); | ||||
|             wl.IsPaused = isPaused; | ||||
|             _dbContext.Update(wl); | ||||
|             await _dbContext.SaveChangesAsync(); | ||||
|             var otherEntry = OppositeEntry(uid); | ||||
|  | ||||
|             await Clients.User(user.UID) | ||||
|                 .SendAsync(Api.OnUserUpdateClientPairs, new ClientPairDto() | ||||
|                 { | ||||
|                     OtherUID = otherUser.UID, | ||||
|                     IsPaused = isPaused, | ||||
|                     IsPausedFromOthers = otherEntry?.IsPaused ?? false, | ||||
|                     IsSynced = otherEntry != null | ||||
|                 }, otherUser.CharacterIdentification); | ||||
|             if (otherEntry != null) | ||||
|             { | ||||
|                 await Clients.User(uid).SendAsync(Api.OnUserUpdateClientPairs, new ClientPairDto() | ||||
|                 { | ||||
|                     OtherUID = user.UID, | ||||
|                     IsPaused = otherEntry.IsPaused, | ||||
|                     IsPausedFromOthers = isPaused, | ||||
|                     IsSynced = true | ||||
|                 }, user.CharacterIdentification); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)] | ||||
|         [HubMethodName(Api.SendUserPairedClientRemoval)] | ||||
|         public async Task SendPairedClientRemoval(string uid) | ||||
|         { | ||||
|             if (uid == AuthenticatedUserId) return; | ||||
|  | ||||
|             var sender = await _dbContext.Users.SingleAsync(u => u.UID == AuthenticatedUserId); | ||||
|             var otherUser = await _dbContext.Users.SingleOrDefaultAsync(u => u.UID == uid); | ||||
|             if (otherUser == null) return; | ||||
|             _logger.LogInformation("User " + AuthenticatedUserId + " removed " + uid + " from whitelist"); | ||||
|             ClientPair wl = | ||||
|                 await _dbContext.ClientPairs.SingleOrDefaultAsync(w => w.User == sender && w.OtherUser == otherUser); | ||||
|             if (wl == null) return; | ||||
|             _dbContext.ClientPairs.Remove(wl); | ||||
|             await _dbContext.SaveChangesAsync(); | ||||
|             var otherEntry = OppositeEntry(uid); | ||||
|             await Clients.User(sender.UID) | ||||
|                 .SendAsync(Api.OnUserUpdateClientPairs, new ClientPairDto() | ||||
|                 { | ||||
|                     OtherUID = otherUser.UID, | ||||
|                     IsRemoved = true | ||||
|                 }, otherUser.CharacterIdentification); | ||||
|             if (otherEntry != null) | ||||
|             { | ||||
|                 if (!string.IsNullOrEmpty(otherUser.CharacterIdentification)) | ||||
|                 { | ||||
|                     await Clients.User(sender.UID) | ||||
|                         .SendAsync(Api.OnUserRemoveOnlinePairedPlayer, otherUser.CharacterIdentification); | ||||
|                     await Clients.User(otherUser.UID) | ||||
|                         .SendAsync(Api.OnUserRemoveOnlinePairedPlayer, sender.CharacterIdentification); | ||||
|                     await Clients.User(otherUser.UID).SendAsync(Api.OnUserUpdateClientPairs, new ClientPairDto() | ||||
|                     { | ||||
|                         OtherUID = sender.UID, | ||||
|                         IsPaused = otherEntry.IsPaused, | ||||
|                         IsPausedFromOthers = false, | ||||
|                         IsSynced = false | ||||
|                     }, sender.CharacterIdentification); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private ClientPair OppositeEntry(string otherUID) => | ||||
|                                     _dbContext.ClientPairs.AsNoTracking().SingleOrDefault(w => w.User.UID == otherUID && w.OtherUser.UID == AuthenticatedUserId); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Stanley Dimant
					Stanley Dimant