update to API 5, consolidate hubs into one
This commit is contained in:
@@ -1,51 +0,0 @@
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
using MareSynchronosServer.Data;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace MareSynchronosServer.Hubs
|
||||
{
|
||||
public abstract class BaseHub<T> : Hub
|
||||
{
|
||||
protected readonly ILogger<T> Logger;
|
||||
protected MareDbContext DbContext { get; init; }
|
||||
|
||||
protected BaseHub(MareDbContext context, ILogger<T> logger)
|
||||
{
|
||||
Logger = logger;
|
||||
DbContext = context;
|
||||
}
|
||||
|
||||
protected string AuthenticatedUserId => Context.User?.Claims?.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value ?? "Unknown";
|
||||
|
||||
protected async Task<Models.User> GetAuthenticatedUserUntrackedAsync()
|
||||
{
|
||||
return await DbContext.Users.AsNoTrackingWithIdentityResolution().SingleAsync(u => u.UID == AuthenticatedUserId);
|
||||
}
|
||||
|
||||
public static string GenerateRandomString(int length, string allowableChars = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(allowableChars))
|
||||
allowableChars = @"ABCDEFGHJKLMNPQRSTUVWXYZ0123456789";
|
||||
|
||||
// Generate random data
|
||||
var rnd = new byte[length];
|
||||
using (var rng = new RNGCryptoServiceProvider())
|
||||
rng.GetBytes(rnd);
|
||||
|
||||
// Generate the output string
|
||||
var allowable = allowableChars.ToCharArray();
|
||||
var l = allowable.Length;
|
||||
var chars = new char[length];
|
||||
for (var i = 0; i < length; i++)
|
||||
chars[i] = allowable[rnd[i] % l];
|
||||
|
||||
return new string(chars);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading.Tasks;
|
||||
using MareSynchronos.API;
|
||||
using MareSynchronosServer.Data;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace MareSynchronosServer.Hubs
|
||||
{
|
||||
public class ConnectionHub : BaseHub<ConnectionHub>
|
||||
{
|
||||
private readonly SystemInfoService _systemInfoService;
|
||||
|
||||
public ConnectionHub(MareDbContext mareDbContext, ILogger<ConnectionHub> logger, SystemInfoService systemInfoService) : base(mareDbContext, logger)
|
||||
{
|
||||
_systemInfoService = systemInfoService;
|
||||
}
|
||||
|
||||
[HubMethodName(ConnectionHubAPI.InvokeHeartbeat)]
|
||||
public async Task<ConnectionDto> Heartbeat(string? characterIdentification)
|
||||
{
|
||||
var userId = Context.User!.Claims.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value;
|
||||
|
||||
Logger.LogInformation("Connection from " + userId + ", CI: " + characterIdentification);
|
||||
|
||||
await Clients.Caller.SendAsync(ConnectionHubAPI.OnUpdateSystemInfo, _systemInfoService.SystemInfoDto);
|
||||
|
||||
var isBanned = await DbContext.BannedUsers.AsNoTracking().AnyAsync(u => u.CharacterIdentification == characterIdentification);
|
||||
|
||||
if (userId != null && !isBanned && !string.IsNullOrEmpty(characterIdentification))
|
||||
{
|
||||
Logger.LogInformation("Connection from " + userId);
|
||||
var user = (await DbContext.Users.SingleAsync(u => u.UID == userId));
|
||||
user.CharacterIdentification = characterIdentification;
|
||||
await DbContext.SaveChangesAsync();
|
||||
return new ConnectionDto
|
||||
{
|
||||
ServerVersion = API.Version,
|
||||
UID = userId,
|
||||
IsModerator = user.IsModerator,
|
||||
IsAdmin = user.IsAdmin
|
||||
};
|
||||
}
|
||||
|
||||
return new ConnectionDto()
|
||||
{
|
||||
ServerVersion = API.Version
|
||||
};
|
||||
}
|
||||
|
||||
[HubMethodName(ConnectionHubAPI.InvokeGetSystemInfo)]
|
||||
public async Task<SystemInfoDto> GetSystemInfo()
|
||||
{
|
||||
return _systemInfoService.SystemInfoDto;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,85 +3,79 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using MareSynchronos.API;
|
||||
using MareSynchronosServer.Authentication;
|
||||
using MareSynchronosServer.Data;
|
||||
using MareSynchronosServer.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace MareSynchronosServer.Hubs
|
||||
{
|
||||
public class AdminHub : BaseHub<AdminHub>
|
||||
public partial class MareHub
|
||||
{
|
||||
public AdminHub(MareDbContext context, ILogger<AdminHub> logger) : base(context, logger)
|
||||
{
|
||||
}
|
||||
private bool IsAdmin => _dbContext.Users.Single(b => b.UID == AuthenticatedUserId).IsAdmin;
|
||||
|
||||
private bool IsAdmin => DbContext.Users.Single(b => b.UID == AuthenticatedUserId).IsAdmin;
|
||||
private bool IsModerator => _dbContext.Users.Single(b => b.UID == AuthenticatedUserId).IsModerator || IsAdmin;
|
||||
|
||||
private bool IsModerator => DbContext.Users.Single(b => b.UID == AuthenticatedUserId).IsModerator || IsAdmin;
|
||||
|
||||
private List<string> OnlineAdmins => DbContext.Users.Where(u => !string.IsNullOrEmpty(u.CharacterIdentification) && (u.IsModerator || u.IsAdmin))
|
||||
private List<string> OnlineAdmins => _dbContext.Users.Where(u => !string.IsNullOrEmpty(u.CharacterIdentification) && (u.IsModerator || u.IsAdmin))
|
||||
.Select(u => u.UID).ToList();
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(AdminHubAPI.SendChangeModeratorStatus)]
|
||||
[HubMethodName(Api.SendAdminChangeModeratorStatus)]
|
||||
public async Task ChangeModeratorStatus(string uid, bool isModerator)
|
||||
{
|
||||
if (!IsAdmin) return;
|
||||
var user = await DbContext.Users.SingleOrDefaultAsync(u => u.UID == uid);
|
||||
var user = await _dbContext.Users.SingleOrDefaultAsync(u => u.UID == uid);
|
||||
|
||||
if (user == null) return;
|
||||
|
||||
user.IsModerator = isModerator;
|
||||
DbContext.Update(user);
|
||||
await DbContext.SaveChangesAsync();
|
||||
await Clients.Users(user.UID).SendAsync(AdminHubAPI.OnForcedReconnect);
|
||||
_dbContext.Update(user);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
await Clients.Users(user.UID).SendAsync(Api.OnAdminForcedReconnect);
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(AdminHubAPI.SendDeleteBannedUser)]
|
||||
[HubMethodName(Api.SendAdminDeleteBannedUser)]
|
||||
public async Task DeleteBannedUser(BannedUserDto dto)
|
||||
{
|
||||
if (!IsModerator || string.IsNullOrEmpty(dto.CharacterHash)) return;
|
||||
|
||||
var existingUser =
|
||||
await DbContext.BannedUsers.SingleOrDefaultAsync(b => b.CharacterIdentification == dto.CharacterHash);
|
||||
await _dbContext.BannedUsers.SingleOrDefaultAsync(b => b.CharacterIdentification == dto.CharacterHash);
|
||||
if (existingUser == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DbContext.Remove(existingUser);
|
||||
await DbContext.SaveChangesAsync();
|
||||
await Clients.Users(OnlineAdmins).SendAsync(AdminHubAPI.OnDeleteBannedUser, dto);
|
||||
_dbContext.Remove(existingUser);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
await Clients.Users(OnlineAdmins).SendAsync(Api.OnAdminDeleteBannedUser, dto);
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(AdminHubAPI.SendDeleteForbiddenFile)]
|
||||
[HubMethodName(Api.SendAdminDeleteForbiddenFile)]
|
||||
public async Task DeleteForbiddenFile(ForbiddenFileDto dto)
|
||||
{
|
||||
if (!IsAdmin || string.IsNullOrEmpty(dto.Hash)) return;
|
||||
|
||||
var existingFile =
|
||||
await DbContext.ForbiddenUploadEntries.SingleOrDefaultAsync(b => b.Hash == dto.Hash);
|
||||
await _dbContext.ForbiddenUploadEntries.SingleOrDefaultAsync(b => b.Hash == dto.Hash);
|
||||
if (existingFile == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DbContext.Remove(existingFile);
|
||||
await DbContext.SaveChangesAsync();
|
||||
await Clients.Users(OnlineAdmins).SendAsync(AdminHubAPI.OnDeleteForbiddenFile, dto);
|
||||
_dbContext.Remove(existingFile);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
await Clients.Users(OnlineAdmins).SendAsync(Api.OnAdminDeleteForbiddenFile, dto);
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(AdminHubAPI.InvokeGetBannedUsers)]
|
||||
[HubMethodName(Api.InvokeAdminGetBannedUsers)]
|
||||
public async Task<List<BannedUserDto>> GetBannedUsers()
|
||||
{
|
||||
if (!IsModerator) return null;
|
||||
|
||||
return await DbContext.BannedUsers.AsNoTracking().Select(b => new BannedUserDto()
|
||||
return await _dbContext.BannedUsers.AsNoTracking().Select(b => new BannedUserDto()
|
||||
{
|
||||
CharacterHash = b.CharacterIdentification,
|
||||
Reason = b.Reason
|
||||
@@ -89,12 +83,12 @@ namespace MareSynchronosServer.Hubs
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(AdminHubAPI.InvokeGetForbiddenFiles)]
|
||||
[HubMethodName(Api.InvokeAdminGetForbiddenFiles)]
|
||||
public async Task<List<ForbiddenFileDto>> GetForbiddenFiles()
|
||||
{
|
||||
if (!IsModerator) return null;
|
||||
|
||||
return await DbContext.ForbiddenUploadEntries.AsNoTracking().Select(b => new ForbiddenFileDto()
|
||||
return await _dbContext.ForbiddenUploadEntries.AsNoTracking().Select(b => new ForbiddenFileDto()
|
||||
{
|
||||
Hash = b.Hash,
|
||||
ForbiddenBy = b.ForbiddenBy
|
||||
@@ -102,12 +96,12 @@ namespace MareSynchronosServer.Hubs
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(AdminHubAPI.InvokeGetOnlineUsers)]
|
||||
public async Task<List<OnlineUserDto>> GetOnlineUsers()
|
||||
[HubMethodName(Api.InvokeUserGetOnlineUsers)]
|
||||
public async Task<List<OnlineUserDto>> AdminGetOnlineUsers()
|
||||
{
|
||||
if (!IsModerator) return null;
|
||||
|
||||
return await DbContext.Users.AsNoTracking().Where(b => !string.IsNullOrEmpty(b.CharacterIdentification)).Select(b => new OnlineUserDto
|
||||
return await _dbContext.Users.AsNoTracking().Where(b => !string.IsNullOrEmpty(b.CharacterIdentification)).Select(b => new OnlineUserDto
|
||||
{
|
||||
CharacterNameHash = b.CharacterIdentification,
|
||||
UID = b.UID,
|
||||
@@ -117,62 +111,62 @@ namespace MareSynchronosServer.Hubs
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(AdminHubAPI.SendUpdateOrAddBannedUser)]
|
||||
[HubMethodName(Api.SendAdminUpdateOrAddBannedUser)]
|
||||
public async Task UpdateOrAddBannedUser(BannedUserDto dto)
|
||||
{
|
||||
if (!IsModerator || string.IsNullOrEmpty(dto.CharacterHash)) return;
|
||||
|
||||
var existingUser =
|
||||
await DbContext.BannedUsers.SingleOrDefaultAsync(b => b.CharacterIdentification == dto.CharacterHash);
|
||||
await _dbContext.BannedUsers.SingleOrDefaultAsync(b => b.CharacterIdentification == dto.CharacterHash);
|
||||
if (existingUser != null)
|
||||
{
|
||||
existingUser.Reason = dto.Reason;
|
||||
DbContext.Update(existingUser);
|
||||
_dbContext.Update(existingUser);
|
||||
}
|
||||
else
|
||||
{
|
||||
await DbContext.BannedUsers.AddAsync(new Banned
|
||||
await _dbContext.BannedUsers.AddAsync(new Banned
|
||||
{
|
||||
CharacterIdentification = dto.CharacterHash,
|
||||
Reason = dto.Reason
|
||||
});
|
||||
}
|
||||
|
||||
await DbContext.SaveChangesAsync();
|
||||
await Clients.Users(OnlineAdmins).SendAsync(AdminHubAPI.OnUpdateOrAddBannedUser, dto);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
await Clients.Users(OnlineAdmins).SendAsync(Api.OnAdminUpdateOrAddBannedUser, dto);
|
||||
var bannedUser =
|
||||
await DbContext.Users.SingleOrDefaultAsync(u => u.CharacterIdentification == dto.CharacterHash);
|
||||
await _dbContext.Users.SingleOrDefaultAsync(u => u.CharacterIdentification == dto.CharacterHash);
|
||||
if (bannedUser != null)
|
||||
{
|
||||
await Clients.User(bannedUser.UID).SendAsync(AdminHubAPI.OnForcedReconnect);
|
||||
await Clients.User(bannedUser.UID).SendAsync(Api.OnAdminForcedReconnect);
|
||||
}
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(AdminHubAPI.SendUpdateOrAddForbiddenFile)]
|
||||
[HubMethodName(Api.SendAdminUpdateOrAddForbiddenFile)]
|
||||
public async Task UpdateOrAddForbiddenFile(ForbiddenFileDto dto)
|
||||
{
|
||||
if (!IsAdmin || string.IsNullOrEmpty(dto.Hash)) return;
|
||||
|
||||
var existingForbiddenFile =
|
||||
await DbContext.ForbiddenUploadEntries.SingleOrDefaultAsync(b => b.Hash == dto.Hash);
|
||||
await _dbContext.ForbiddenUploadEntries.SingleOrDefaultAsync(b => b.Hash == dto.Hash);
|
||||
if (existingForbiddenFile != null)
|
||||
{
|
||||
existingForbiddenFile.ForbiddenBy = dto.ForbiddenBy;
|
||||
DbContext.Update(existingForbiddenFile);
|
||||
_dbContext.Update(existingForbiddenFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
await DbContext.ForbiddenUploadEntries.AddAsync(new ForbiddenUploadEntry
|
||||
await _dbContext.ForbiddenUploadEntries.AddAsync(new ForbiddenUploadEntry
|
||||
{
|
||||
Hash = dto.Hash,
|
||||
ForbiddenBy = dto.ForbiddenBy
|
||||
});
|
||||
}
|
||||
|
||||
await DbContext.SaveChangesAsync();
|
||||
await _dbContext.SaveChangesAsync();
|
||||
|
||||
await Clients.Users(OnlineAdmins).SendAsync(AdminHubAPI.OnUpdateOrAddForbiddenFile, dto);
|
||||
await Clients.Users(OnlineAdmins).SendAsync(Api.OnAdminUpdateOrAddForbiddenFile, dto);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
@@ -10,60 +8,51 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MareSynchronos.API;
|
||||
using MareSynchronosServer.Authentication;
|
||||
using MareSynchronosServer.Data;
|
||||
using MareSynchronosServer.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace MareSynchronosServer.Hubs
|
||||
{
|
||||
public class FilesHub : BaseHub<FilesHub>
|
||||
public partial class MareHub
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public FilesHub(ILogger<FilesHub> logger, MareDbContext context, IConfiguration configuration) : base(context, logger)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
private string BasePath => _configuration["CacheDirectory"];
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(FilesHubAPI.SendAbortUpload)]
|
||||
[HubMethodName(Api.SendFileAbortUpload)]
|
||||
public async Task AbortUpload()
|
||||
{
|
||||
Logger.LogInformation("User " + AuthenticatedUserId + " aborted upload");
|
||||
_logger.LogInformation("User " + AuthenticatedUserId + " aborted upload");
|
||||
var userId = AuthenticatedUserId;
|
||||
var notUploadedFiles = DbContext.Files.Where(f => !f.Uploaded && f.Uploader.UID == userId).ToList();
|
||||
DbContext.RemoveRange(notUploadedFiles);
|
||||
await DbContext.SaveChangesAsync();
|
||||
var notUploadedFiles = _dbContext.Files.Where(f => !f.Uploaded && f.Uploader.UID == userId).ToList();
|
||||
_dbContext.RemoveRange(notUploadedFiles);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(FilesHubAPI.SendDeleteAllFiles)]
|
||||
[HubMethodName(Api.SendFileDeleteAllFiles)]
|
||||
public async Task DeleteAllFiles()
|
||||
{
|
||||
Logger.LogInformation("User " + AuthenticatedUserId + " deleted all their files");
|
||||
_logger.LogInformation("User " + AuthenticatedUserId + " deleted all their files");
|
||||
|
||||
var ownFiles = await DbContext.Files.Where(f => f.Uploaded && f.Uploader.UID == AuthenticatedUserId).ToListAsync();
|
||||
var ownFiles = await _dbContext.Files.Where(f => f.Uploaded && f.Uploader.UID == AuthenticatedUserId).ToListAsync();
|
||||
foreach (var file in ownFiles)
|
||||
{
|
||||
File.Delete(Path.Combine(BasePath, file.Hash));
|
||||
}
|
||||
DbContext.Files.RemoveRange(ownFiles);
|
||||
await DbContext.SaveChangesAsync();
|
||||
_dbContext.Files.RemoveRange(ownFiles);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(FilesHubAPI.StreamDownloadFileAsync)]
|
||||
[HubMethodName(Api.StreamFileDownloadFileAsync)]
|
||||
public async IAsyncEnumerable<byte[]> DownloadFileAsync(string hash, [EnumeratorCancellation] CancellationToken ct)
|
||||
{
|
||||
Logger.LogInformation("User " + AuthenticatedUserId + " downloading file: " + hash);
|
||||
_logger.LogInformation("User " + AuthenticatedUserId + " downloading file: " + hash);
|
||||
|
||||
var file = DbContext.Files.AsNoTracking()
|
||||
var file = _dbContext.Files.AsNoTracking()
|
||||
.SingleOrDefault(f => f.Hash == hash);
|
||||
if (file == null) yield break;
|
||||
var chunkSize = 1024 * 512; // 512kb
|
||||
@@ -77,15 +66,15 @@ namespace MareSynchronosServer.Hubs
|
||||
yield return readByteCount == chunkSize ? buffer.ToArray() : buffer.Take(readByteCount).ToArray();
|
||||
}
|
||||
|
||||
Logger.LogInformation("User " + AuthenticatedUserId + " finished downloading file: " + hash);
|
||||
_logger.LogInformation("User " + AuthenticatedUserId + " finished downloading file: " + hash);
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(FilesHubAPI.InvokeGetFileSize)]
|
||||
[HubMethodName(Api.InvokeFileGetFileSize)]
|
||||
public async Task<DownloadFileDto> GetFileSize(string hash)
|
||||
{
|
||||
var file = await DbContext.Files.AsNoTracking().SingleOrDefaultAsync(f => f.Hash == hash);
|
||||
var forbidden = DbContext.ForbiddenUploadEntries.AsNoTracking().
|
||||
var file = await _dbContext.Files.AsNoTracking().SingleOrDefaultAsync(f => f.Hash == hash);
|
||||
var forbidden = _dbContext.ForbiddenUploadEntries.AsNoTracking().
|
||||
SingleOrDefault(f => f.Hash == hash);
|
||||
var fileInfo = new FileInfo(Path.Combine(BasePath, hash));
|
||||
long fileSize = 0;
|
||||
@@ -109,8 +98,8 @@ namespace MareSynchronosServer.Hubs
|
||||
|
||||
if (!fileInfo.Exists && file != null)
|
||||
{
|
||||
DbContext.Files.Remove(file);
|
||||
await DbContext.SaveChangesAsync();
|
||||
_dbContext.Files.Remove(file);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
return response;
|
||||
@@ -118,30 +107,21 @@ namespace MareSynchronosServer.Hubs
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(FilesHubAPI.InvokeIsUploadFinished)]
|
||||
[HubMethodName(Api.InvokeFileIsUploadFinished)]
|
||||
public async Task<bool> IsUploadFinished()
|
||||
{
|
||||
var userUid = AuthenticatedUserId;
|
||||
return await DbContext.Files.AsNoTracking()
|
||||
return await _dbContext.Files.AsNoTracking()
|
||||
.AnyAsync(f => f.Uploader.UID == userUid && !f.Uploaded);
|
||||
}
|
||||
|
||||
public override Task OnDisconnectedAsync(Exception exception)
|
||||
{
|
||||
var userId = AuthenticatedUserId;
|
||||
var notUploadedFiles = DbContext.Files.Where(f => !f.Uploaded && f.Uploader.UID == userId).ToList();
|
||||
DbContext.RemoveRange(notUploadedFiles);
|
||||
DbContext.SaveChanges();
|
||||
return base.OnDisconnectedAsync(exception);
|
||||
}
|
||||
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(FilesHubAPI.InvokeSendFiles)]
|
||||
[HubMethodName(Api.InvokeFileSendFiles)]
|
||||
public async Task<List<UploadFileDto>> SendFiles(List<string> fileListHashes)
|
||||
{
|
||||
fileListHashes = fileListHashes.Where(f => !string.IsNullOrEmpty(f)).Distinct().ToList();
|
||||
Logger.LogInformation("User " + AuthenticatedUserId + " sending files");
|
||||
var forbiddenFiles = await DbContext.ForbiddenUploadEntries.AsNoTracking().Where(f => fileListHashes.Contains(f.Hash)).ToListAsync();
|
||||
_logger.LogInformation("User " + AuthenticatedUserId + " sending files");
|
||||
var forbiddenFiles = await _dbContext.ForbiddenUploadEntries.AsNoTracking().Where(f => fileListHashes.Contains(f.Hash)).ToListAsync();
|
||||
var filesToUpload = new List<UploadFileDto>();
|
||||
filesToUpload.AddRange(forbiddenFiles.Select(f => new UploadFileDto()
|
||||
{
|
||||
@@ -150,18 +130,18 @@ namespace MareSynchronosServer.Hubs
|
||||
IsForbidden = true
|
||||
}));
|
||||
fileListHashes.RemoveAll(f => filesToUpload.Any(u => u.Hash == f));
|
||||
var existingFiles = await DbContext.Files.AsNoTracking().Where(f => fileListHashes.Contains(f.Hash)).ToListAsync();
|
||||
var existingFiles = await _dbContext.Files.AsNoTracking().Where(f => fileListHashes.Contains(f.Hash)).ToListAsync();
|
||||
foreach (var file in fileListHashes.Where(f => existingFiles.All(e => e.Hash != f) && filesToUpload.All(u => u.Hash != f)))
|
||||
{
|
||||
Logger.LogInformation("User " + AuthenticatedUserId + " needs upload: " + file);
|
||||
_logger.LogInformation("User " + AuthenticatedUserId + " needs upload: " + file);
|
||||
var userId = AuthenticatedUserId;
|
||||
await DbContext.Files.AddAsync(new FileCache()
|
||||
await _dbContext.Files.AddAsync(new FileCache()
|
||||
{
|
||||
Hash = file,
|
||||
Uploaded = false,
|
||||
Uploader = DbContext.Users.Single(u => u.UID == userId)
|
||||
Uploader = _dbContext.Users.Single(u => u.UID == userId)
|
||||
});
|
||||
await DbContext.SaveChangesAsync();
|
||||
await _dbContext.SaveChangesAsync();
|
||||
filesToUpload.Add(new UploadFileDto
|
||||
{
|
||||
Hash = file
|
||||
@@ -172,14 +152,14 @@ namespace MareSynchronosServer.Hubs
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(FilesHubAPI.SendUploadFileStreamAsync)]
|
||||
[HubMethodName(Api.SendFileUploadFileStreamAsync)]
|
||||
public async Task UploadFileStreamAsync(string hash, IAsyncEnumerable<byte[]> fileContent)
|
||||
{
|
||||
Logger.LogInformation("User " + AuthenticatedUserId + " uploading file: " + hash);
|
||||
_logger.LogInformation("User " + AuthenticatedUserId + " uploading file: " + hash);
|
||||
|
||||
var relatedFile = DbContext.Files.SingleOrDefault(f => f.Hash == hash && f.Uploader.UID == AuthenticatedUserId && f.Uploaded == false);
|
||||
var relatedFile = _dbContext.Files.SingleOrDefault(f => f.Hash == hash && f.Uploader.UID == AuthenticatedUserId && f.Uploaded == false);
|
||||
if (relatedFile == null) return;
|
||||
var forbiddenFile = DbContext.ForbiddenUploadEntries.SingleOrDefault(f => f.Hash == hash);
|
||||
var forbiddenFile = _dbContext.ForbiddenUploadEntries.SingleOrDefault(f => f.Hash == hash);
|
||||
if (forbiddenFile != null) return;
|
||||
var uploadedFile = new List<byte>();
|
||||
try
|
||||
@@ -193,8 +173,8 @@ namespace MareSynchronosServer.Hubs
|
||||
{
|
||||
try
|
||||
{
|
||||
DbContext.Files.Remove(relatedFile);
|
||||
await DbContext.SaveChangesAsync();
|
||||
_dbContext.Files.Remove(relatedFile);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -204,7 +184,7 @@ namespace MareSynchronosServer.Hubs
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogInformation("User " + AuthenticatedUserId + " upload finished: " + hash + ", size: " + uploadedFile.Count);
|
||||
_logger.LogInformation("User " + AuthenticatedUserId + " upload finished: " + hash + ", size: " + uploadedFile.Count);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -214,24 +194,24 @@ namespace MareSynchronosServer.Hubs
|
||||
var computedHashString = BitConverter.ToString(computedHash).Replace("-", "");
|
||||
if (hash != computedHashString)
|
||||
{
|
||||
Logger.LogWarning($"Computed file hash was not expected file hash. Computed: {computedHashString}, Expected {hash}");
|
||||
DbContext.Remove(relatedFile);
|
||||
await DbContext.SaveChangesAsync();
|
||||
_logger.LogWarning($"Computed file hash was not expected file hash. Computed: {computedHashString}, Expected {hash}");
|
||||
_dbContext.Remove(relatedFile);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await File.WriteAllBytesAsync(Path.Combine(BasePath, hash), uploadedFile.ToArray());
|
||||
relatedFile = DbContext.Files.Single(f => f.Hash == hash);
|
||||
relatedFile = _dbContext.Files.Single(f => f.Hash == hash);
|
||||
relatedFile.Uploaded = true;
|
||||
await DbContext.SaveChangesAsync();
|
||||
Logger.LogInformation("File " + hash + " added to DB");
|
||||
await _dbContext.SaveChangesAsync();
|
||||
_logger.LogInformation("File " + hash + " added to DB");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogWarning(ex, "Upload failed");
|
||||
DbContext.Remove(relatedFile);
|
||||
await DbContext.SaveChangesAsync();
|
||||
_logger.LogWarning(ex, "Upload failed");
|
||||
_dbContext.Remove(relatedFile);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MareSynchronos.API;
|
||||
using MareSynchronosServer.Authentication;
|
||||
using MareSynchronosServer.Data;
|
||||
using MareSynchronosServer.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
@@ -16,73 +14,69 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace MareSynchronosServer.Hubs
|
||||
{
|
||||
public class UserHub : BaseHub<UserHub>
|
||||
public partial class MareHub
|
||||
{
|
||||
public UserHub(ILogger<UserHub> logger, MareDbContext dbContext) : base(dbContext, logger)
|
||||
{
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(UserHubAPI.SendDeleteAccount)]
|
||||
[HubMethodName(Api.SendUserDeleteAccount)]
|
||||
public async Task DeleteAccount()
|
||||
{
|
||||
Logger.LogInformation("User " + AuthenticatedUserId + " deleted their account");
|
||||
_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);
|
||||
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(UserHubAPI.OnUpdateClientPairs, new ClientPairDto()
|
||||
.SendAsync(Api.OnUserUpdateClientPairs, new ClientPairDto()
|
||||
{
|
||||
OtherUID = userid,
|
||||
IsRemoved = true
|
||||
}, userEntry.CharacterIdentification);
|
||||
}
|
||||
|
||||
DbContext.RemoveRange(otherPairData);
|
||||
DbContext.Remove(userEntry);
|
||||
await DbContext.SaveChangesAsync();
|
||||
_dbContext.RemoveRange(otherPairData);
|
||||
_dbContext.Remove(userEntry);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(UserHubAPI.InvokeGetOnlineCharacters)]
|
||||
[HubMethodName(Api.InvokeUserGetOnlineCharacters)]
|
||||
public async Task<List<string>> GetOnlineCharacters()
|
||||
{
|
||||
Logger.LogInformation("User " + AuthenticatedUserId + " requested online characters");
|
||||
_logger.LogInformation("User " + AuthenticatedUserId + " requested online characters");
|
||||
|
||||
var ownUser = await GetAuthenticatedUserUntrackedAsync();
|
||||
|
||||
var otherUsers = await DbContext.ClientPairs.AsNoTracking()
|
||||
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()
|
||||
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(UserHubAPI.OnAddOnlinePairedPlayer, ownUser.CharacterIdentification);
|
||||
await Clients.Users(otherEntries.Select(e => e.User.UID)).SendAsync(Api.OnUserAddOnlinePairedPlayer, ownUser.CharacterIdentification);
|
||||
return otherEntries.Select(e => e.User.CharacterIdentification).Distinct().ToList();
|
||||
}
|
||||
|
||||
[HubMethodName(UserHubAPI.InvokeGetOnlineUsers)]
|
||||
[HubMethodName(Api.InvokeAdminGetOnlineUsers)]
|
||||
public async Task<int> GetOnlineUsers()
|
||||
{
|
||||
return await DbContext.Users.CountAsync(u => !string.IsNullOrEmpty(u.CharacterIdentification));
|
||||
return await _dbContext.Users.CountAsync(u => !string.IsNullOrEmpty(u.CharacterIdentification));
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(UserHubAPI.InvokeGetPairedClients)]
|
||||
[HubMethodName(Api.InvokeUserGetPairedClients)]
|
||||
public async Task<List<ClientPairDto>> GetPairedClients()
|
||||
{
|
||||
string userid = AuthenticatedUserId;
|
||||
var pairs = await DbContext.ClientPairs.AsNoTracking()
|
||||
var pairs = await _dbContext.ClientPairs.AsNoTracking()
|
||||
.Include(u => u.OtherUser)
|
||||
.Include(u => u.User)
|
||||
.Where(w => w.User.UID == userid)
|
||||
@@ -100,42 +94,16 @@ namespace MareSynchronosServer.Hubs
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
public override async Task OnDisconnectedAsync(Exception exception)
|
||||
{
|
||||
var user = await DbContext.Users.AsNoTracking().SingleOrDefaultAsync(u => u.UID == AuthenticatedUserId);
|
||||
if (user != null && !string.IsNullOrEmpty(user.CharacterIdentification))
|
||||
{
|
||||
Logger.LogInformation("Disconnect from " + AuthenticatedUserId);
|
||||
|
||||
var otherUsers = await DbContext.ClientPairs.AsNoTracking()
|
||||
.Include(u => u.User)
|
||||
.Include(u => u.OtherUser)
|
||||
.Where(w => w.User.UID == user.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.UID == user.UID && !u.IsPaused).ToListAsync();
|
||||
await Clients.Users(otherEntries.Select(e => e.User.UID)).SendAsync(UserHubAPI.OnRemoveOnlinePairedPlayer, user.CharacterIdentification);
|
||||
|
||||
|
||||
(await DbContext.Users.SingleAsync(u => u.UID == AuthenticatedUserId)).CharacterIdentification = null;
|
||||
await DbContext.SaveChangesAsync();
|
||||
|
||||
await Clients.All.SendAsync("UsersOnline",
|
||||
await DbContext.Users.CountAsync(u => !string.IsNullOrEmpty(u.CharacterIdentification)));
|
||||
}
|
||||
|
||||
await base.OnDisconnectedAsync(exception);
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(UserHubAPI.InvokePushCharacterDataToVisibleClients)]
|
||||
[HubMethodName(Api.InvokeUserPushCharacterDataToVisibleClients)]
|
||||
public async Task PushCharacterDataToVisibleClients(CharacterCacheDto characterCache, List<string> visibleCharacterIds)
|
||||
{
|
||||
Logger.LogInformation("User " + AuthenticatedUserId + " pushing character data to " + visibleCharacterIds.Count + " visible clients");
|
||||
_logger.LogInformation("User " + AuthenticatedUserId + " pushing character data to " + visibleCharacterIds.Count + " visible clients");
|
||||
|
||||
var user = await GetAuthenticatedUserUntrackedAsync();
|
||||
var senderPairedUsers = await DbContext.ClientPairs.AsNoTracking()
|
||||
var senderPairedUsers = await _dbContext.ClientPairs.AsNoTracking()
|
||||
.Include(w => w.User)
|
||||
.Include(w => w.OtherUser)
|
||||
.Where(w => w.User.UID == user.UID && !w.IsPaused
|
||||
@@ -144,77 +112,81 @@ namespace MareSynchronosServer.Hubs
|
||||
|
||||
foreach (var pairedUser in senderPairedUsers)
|
||||
{
|
||||
var isPaused = (await DbContext.ClientPairs.AsNoTracking()
|
||||
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(UserHubAPI.OnReceiveCharacterData, characterCache,
|
||||
await Clients.User(pairedUser.UID).SendAsync(Api.OnUserReceiveCharacterData, characterCache,
|
||||
user.CharacterIdentification);
|
||||
}
|
||||
}
|
||||
|
||||
[HubMethodName(UserHubAPI.InvokeRegister)]
|
||||
[HubMethodName(Api.InvokeUserRegister)]
|
||||
public async Task<string> Register()
|
||||
{
|
||||
using var sha256 = SHA256.Create();
|
||||
var computedHash = BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(GenerateRandomString(64)))).Replace("-", "");
|
||||
var user = new Models.User
|
||||
{
|
||||
SecretKey = BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(computedHash)))
|
||||
.Replace("-", ""),
|
||||
};
|
||||
var user = new User();
|
||||
|
||||
var hasValidUid = false;
|
||||
while (!hasValidUid)
|
||||
{
|
||||
var uid = GenerateRandomString(10);
|
||||
if (DbContext.Users.Any(u => u.UID == uid)) continue;
|
||||
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())
|
||||
if (!await _dbContext.Users.AnyAsync())
|
||||
{
|
||||
user.IsAdmin = true;
|
||||
}
|
||||
|
||||
DbContext.Users.Add(user);
|
||||
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
|
||||
};
|
||||
|
||||
Logger.LogInformation("User registered: " + user.UID);
|
||||
_dbContext.Users.Add(user);
|
||||
_dbContext.Auth.Add(auth);
|
||||
|
||||
await DbContext.SaveChangesAsync();
|
||||
_logger.LogInformation("User registered: " + user.UID);
|
||||
|
||||
await _dbContext.SaveChangesAsync();
|
||||
return computedHash;
|
||||
}
|
||||
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(UserHubAPI.SendPairedClientAddition)]
|
||||
[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 user = await _dbContext.Users.SingleAsync(u => u.UID == AuthenticatedUserId);
|
||||
|
||||
var otherUser = await DbContext.Users
|
||||
var otherUser = await _dbContext.Users
|
||||
.SingleOrDefaultAsync(u => u.UID == uid);
|
||||
var existingEntry =
|
||||
await DbContext.ClientPairs.AsNoTracking()
|
||||
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");
|
||||
_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();
|
||||
await _dbContext.ClientPairs.AddAsync(wl);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
var otherEntry = OppositeEntry(uid);
|
||||
await Clients.User(user.UID)
|
||||
.SendAsync(UserHubAPI.OnUpdateClientPairs, new ClientPairDto()
|
||||
.SendAsync(Api.OnUserUpdateClientPairs, new ClientPairDto()
|
||||
{
|
||||
OtherUID = otherUser.UID,
|
||||
IsPaused = false,
|
||||
@@ -223,7 +195,7 @@ namespace MareSynchronosServer.Hubs
|
||||
}, string.Empty);
|
||||
if (otherEntry != null)
|
||||
{
|
||||
await Clients.User(uid).SendAsync(UserHubAPI.OnUpdateClientPairs,
|
||||
await Clients.User(uid).SendAsync(Api.OnUserUpdateClientPairs,
|
||||
new ClientPairDto()
|
||||
{
|
||||
OtherUID = user.UID,
|
||||
@@ -235,33 +207,33 @@ namespace MareSynchronosServer.Hubs
|
||||
if (!string.IsNullOrEmpty(otherUser.CharacterIdentification))
|
||||
{
|
||||
await Clients.User(user.UID)
|
||||
.SendAsync(UserHubAPI.OnAddOnlinePairedPlayer, otherUser.CharacterIdentification);
|
||||
.SendAsync(Api.OnUserAddOnlinePairedPlayer, otherUser.CharacterIdentification);
|
||||
await Clients.User(otherUser.UID)
|
||||
.SendAsync(UserHubAPI.OnAddOnlinePairedPlayer, user.CharacterIdentification);
|
||||
.SendAsync(Api.OnUserAddOnlinePairedPlayer, user.CharacterIdentification);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(UserHubAPI.SendPairedClientPauseChange)]
|
||||
[HubMethodName(Api.SendUserPairedClientPauseChange)]
|
||||
public async Task SendPairedClientPauseChange(string uid, bool isPaused)
|
||||
{
|
||||
if (uid == AuthenticatedUserId) return;
|
||||
var user = await DbContext.Users.AsNoTracking()
|
||||
var user = await _dbContext.Users.AsNoTracking()
|
||||
.SingleAsync(u => u.UID == AuthenticatedUserId);
|
||||
var otherUser = await DbContext.Users.AsNoTracking()
|
||||
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);
|
||||
_logger.LogInformation("User " + AuthenticatedUserId + " changed pause status with " + uid + " to " + isPaused);
|
||||
ClientPair wl =
|
||||
await DbContext.ClientPairs.SingleOrDefaultAsync(w => w.User == user && w.OtherUser == otherUser);
|
||||
await _dbContext.ClientPairs.SingleOrDefaultAsync(w => w.User == user && w.OtherUser == otherUser);
|
||||
wl.IsPaused = isPaused;
|
||||
DbContext.Update(wl);
|
||||
await DbContext.SaveChangesAsync();
|
||||
_dbContext.Update(wl);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
var otherEntry = OppositeEntry(uid);
|
||||
|
||||
await Clients.User(user.UID)
|
||||
.SendAsync(UserHubAPI.OnUpdateClientPairs, new ClientPairDto()
|
||||
.SendAsync(Api.OnUserUpdateClientPairs, new ClientPairDto()
|
||||
{
|
||||
OtherUID = otherUser.UID,
|
||||
IsPaused = isPaused,
|
||||
@@ -270,7 +242,7 @@ namespace MareSynchronosServer.Hubs
|
||||
}, otherUser.CharacterIdentification);
|
||||
if (otherEntry != null)
|
||||
{
|
||||
await Clients.User(uid).SendAsync(UserHubAPI.OnUpdateClientPairs, new ClientPairDto()
|
||||
await Clients.User(uid).SendAsync(Api.OnUserUpdateClientPairs, new ClientPairDto()
|
||||
{
|
||||
OtherUID = user.UID,
|
||||
IsPaused = otherEntry.IsPaused,
|
||||
@@ -281,23 +253,23 @@ namespace MareSynchronosServer.Hubs
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||
[HubMethodName(UserHubAPI.SendPairedClientRemoval)]
|
||||
[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);
|
||||
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");
|
||||
_logger.LogInformation("User " + AuthenticatedUserId + " removed " + uid + " from whitelist");
|
||||
ClientPair wl =
|
||||
await DbContext.ClientPairs.SingleOrDefaultAsync(w => w.User == sender && w.OtherUser == otherUser);
|
||||
await _dbContext.ClientPairs.SingleOrDefaultAsync(w => w.User == sender && w.OtherUser == otherUser);
|
||||
if (wl == null) return;
|
||||
DbContext.ClientPairs.Remove(wl);
|
||||
await DbContext.SaveChangesAsync();
|
||||
_dbContext.ClientPairs.Remove(wl);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
var otherEntry = OppositeEntry(uid);
|
||||
await Clients.User(sender.UID)
|
||||
.SendAsync(UserHubAPI.OnUpdateClientPairs, new ClientPairDto()
|
||||
.SendAsync(Api.OnUserUpdateClientPairs, new ClientPairDto()
|
||||
{
|
||||
OtherUID = otherUser.UID,
|
||||
IsRemoved = true
|
||||
@@ -307,10 +279,10 @@ namespace MareSynchronosServer.Hubs
|
||||
if (!string.IsNullOrEmpty(otherUser.CharacterIdentification))
|
||||
{
|
||||
await Clients.User(sender.UID)
|
||||
.SendAsync(UserHubAPI.OnRemoveOnlinePairedPlayer, otherUser.CharacterIdentification);
|
||||
.SendAsync(Api.OnUserRemoveOnlinePairedPlayer, otherUser.CharacterIdentification);
|
||||
await Clients.User(otherUser.UID)
|
||||
.SendAsync(UserHubAPI.OnRemoveOnlinePairedPlayer, sender.CharacterIdentification);
|
||||
await Clients.User(otherUser.UID).SendAsync(UserHubAPI.OnUpdateClientPairs, new ClientPairDto()
|
||||
.SendAsync(Api.OnUserRemoveOnlinePairedPlayer, sender.CharacterIdentification);
|
||||
await Clients.User(otherUser.UID).SendAsync(Api.OnUserUpdateClientPairs, new ClientPairDto()
|
||||
{
|
||||
OtherUID = sender.UID,
|
||||
IsPaused = otherEntry.IsPaused,
|
||||
@@ -322,6 +294,6 @@ namespace MareSynchronosServer.Hubs
|
||||
}
|
||||
|
||||
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 == AuthenticatedUserId);
|
||||
}
|
||||
}
|
||||
125
MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs
Normal file
125
MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
using MareSynchronos.API;
|
||||
using MareSynchronosServer.Data;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace MareSynchronosServer.Hubs
|
||||
{
|
||||
public partial class MareHub : Hub
|
||||
{
|
||||
private readonly SystemInfoService _systemInfoService;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ILogger<MareHub> _logger;
|
||||
private readonly MareDbContext _dbContext;
|
||||
|
||||
public MareHub(MareDbContext mareDbContext, ILogger<MareHub> logger, SystemInfoService systemInfoService, IConfiguration configuration)
|
||||
{
|
||||
_systemInfoService = systemInfoService;
|
||||
_configuration = configuration;
|
||||
_logger = logger;
|
||||
_dbContext = mareDbContext;
|
||||
}
|
||||
|
||||
[HubMethodName(Api.InvokeHeartbeat)]
|
||||
public async Task<ConnectionDto> Heartbeat(string? characterIdentification)
|
||||
{
|
||||
var userId = Context.User!.Claims.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value;
|
||||
|
||||
_logger.LogInformation("Connection from " + userId + ", CI: " + characterIdentification);
|
||||
|
||||
await Clients.Caller.SendAsync(Api.OnUpdateSystemInfo, _systemInfoService.SystemInfoDto);
|
||||
|
||||
var isBanned = await _dbContext.BannedUsers.AsNoTracking().AnyAsync(u => u.CharacterIdentification == characterIdentification);
|
||||
|
||||
if (userId != null && !isBanned && !string.IsNullOrEmpty(characterIdentification))
|
||||
{
|
||||
_logger.LogInformation("Connection from " + userId);
|
||||
var user = (await _dbContext.Users.SingleAsync(u => u.UID == userId));
|
||||
user.CharacterIdentification = characterIdentification;
|
||||
await _dbContext.SaveChangesAsync();
|
||||
return new ConnectionDto
|
||||
{
|
||||
ServerVersion = Api.Version,
|
||||
UID = userId,
|
||||
IsModerator = user.IsModerator,
|
||||
IsAdmin = user.IsAdmin
|
||||
};
|
||||
}
|
||||
|
||||
return new ConnectionDto()
|
||||
{
|
||||
ServerVersion = Api.Version
|
||||
};
|
||||
}
|
||||
|
||||
[HubMethodName(Api.InvokeGetSystemInfo)]
|
||||
public async Task<SystemInfoDto> GetSystemInfo()
|
||||
{
|
||||
return _systemInfoService.SystemInfoDto;
|
||||
}
|
||||
|
||||
public override async Task OnDisconnectedAsync(Exception exception)
|
||||
{
|
||||
var user = await _dbContext.Users.AsNoTracking().SingleOrDefaultAsync(u => u.UID == AuthenticatedUserId);
|
||||
if (user != null && !string.IsNullOrEmpty(user.CharacterIdentification))
|
||||
{
|
||||
_logger.LogInformation("Disconnect from " + AuthenticatedUserId);
|
||||
|
||||
var otherUsers = await _dbContext.ClientPairs.AsNoTracking()
|
||||
.Include(u => u.User)
|
||||
.Include(u => u.OtherUser)
|
||||
.Where(w => w.User.UID == user.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.UID == user.UID && !u.IsPaused).ToListAsync();
|
||||
await Clients.Users(otherEntries.Select(e => e.User.UID)).SendAsync(Api.OnUserRemoveOnlinePairedPlayer, user.CharacterIdentification);
|
||||
|
||||
var notUploadedFiles = _dbContext.Files.Where(f => !f.Uploaded && f.Uploader.UID == user.UID).ToList();
|
||||
_dbContext.RemoveRange(notUploadedFiles);
|
||||
|
||||
(await _dbContext.Users.SingleAsync(u => u.UID == AuthenticatedUserId)).CharacterIdentification = null;
|
||||
await _dbContext.SaveChangesAsync();
|
||||
|
||||
await Clients.All.SendAsync("UsersOnline",
|
||||
await _dbContext.Users.CountAsync(u => !string.IsNullOrEmpty(u.CharacterIdentification)));
|
||||
}
|
||||
|
||||
await base.OnDisconnectedAsync(exception);
|
||||
}
|
||||
|
||||
public static string GenerateRandomString(int length, string allowableChars = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(allowableChars))
|
||||
allowableChars = @"ABCDEFGHJKLMNPQRSTUVWXYZ0123456789";
|
||||
|
||||
// Generate random data
|
||||
var rnd = new byte[length];
|
||||
using (var rng = new RNGCryptoServiceProvider())
|
||||
rng.GetBytes(rnd);
|
||||
|
||||
// Generate the output string
|
||||
var allowable = allowableChars.ToCharArray();
|
||||
var l = allowable.Length;
|
||||
var chars = new char[length];
|
||||
for (var i = 0; i < length; i++)
|
||||
chars[i] = allowable[rnd[i] % l];
|
||||
|
||||
return new string(chars);
|
||||
}
|
||||
|
||||
protected string AuthenticatedUserId => Context.User?.Claims?.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value ?? "Unknown";
|
||||
|
||||
protected async Task<Models.User> GetAuthenticatedUserUntrackedAsync()
|
||||
{
|
||||
return await _dbContext.Users.AsNoTrackingWithIdentityResolution().SingleAsync(u => u.UID == AuthenticatedUserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user