update to API 5, consolidate hubs into one

This commit is contained in:
Stanley Dimant
2022-07-13 14:05:42 +02:00
parent 4a83a7dba0
commit a416521aab
21 changed files with 907 additions and 418 deletions

View File

@@ -6,69 +6,51 @@ using System.Threading.Tasks;
namespace MareSynchronos.API
{
public class API
public class Api
{
public const int Version = 4;
}
public const int Version = 5;
public const string Path = "/mare";
public class FilesHubAPI
{
public const string Path = "/files";
public const string SendFileAbortUpload = "AbortUpload";
public const string InvokeFileSendFiles = "SendFiles";
public const string InvokeFileIsUploadFinished = "IsUploadFinished";
public const string SendFileUploadFileStreamAsync = "UploadFileStreamAsync";
public const string InvokeFileGetFileSize = "GetFileSize";
public const string StreamFileDownloadFileAsync = "StreamDownloadFileAsync";
public const string SendFileDeleteAllFiles = "DeleteAllFiles";
public const string SendAbortUpload = "AbortUpload";
public const string InvokeSendFiles = "SendFiles";
public const string InvokeIsUploadFinished = "IsUploadFinished";
public const string SendUploadFileStreamAsync = "UploadFileStreamAsync";
public const string InvokeGetFileSize = "GetFileSize";
public const string StreamDownloadFileAsync = "StreamDownloadFileAsync";
public const string SendDeleteAllFiles = "DeleteAllFiles";
}
public class ConnectionHubAPI
{
public const string Path = "/heartbeat";
public const string InvokeHeartbeat = "Heartbeat";
public const string InvokeGetSystemInfo = "GetSystemInfo";
public const string OnUpdateSystemInfo = "OnUpdateSystemInfo";
}
public class AdminHubAPI
{
public const string Path = "/admin";
public const string InvokeAdminGetOnlineUsers = "AdminGetOnlineUsers";
public const string InvokeAdminGetBannedUsers = "GetBannedUsers";
public const string SendAdminUpdateOrAddBannedUser = "UpdateOrAddBannedUser";
public const string SendAdminDeleteBannedUser = "DeleteBannedUser";
public const string InvokeAdminGetForbiddenFiles = "GetForbiddenFiles";
public const string SendAdminUpdateOrAddForbiddenFile = "UpdateOrAddForbiddenFile";
public const string SendAdminDeleteForbiddenFile = "DeleteForbiddenFile";
public const string SendAdminChangeModeratorStatus = "ChangeModeratorStatus";
public const string InvokeGetOnlineUsers = "GetOnlineUsers";
public const string InvokeGetBannedUsers = "GetBannedUsers";
public const string SendUpdateOrAddBannedUser = "UpdateOrAddBannedUser";
public const string SendDeleteBannedUser = "DeleteBannedUser";
public const string InvokeGetForbiddenFiles = "GetForbiddenFiles";
public const string SendUpdateOrAddForbiddenFile = "UpdateOrAddForbiddenFile";
public const string SendDeleteForbiddenFile = "DeleteForbiddenFile";
public const string SendChangeModeratorStatus = "ChangeModeratorStatus";
public const string OnAdminForcedReconnect = "OnForcedReconnect";
public const string OnAdminUpdateOrAddBannedUser = "OnUpdateOrAddBannedUser";
public const string OnAdminDeleteBannedUser = "OnDeleteBannedUser";
public const string OnAdminUpdateOrAddForbiddenFile = "OnUpdateOrAddForbiddenFile";
public const string OnAdminDeleteForbiddenFile = "OnDeleteForbiddenFile";
public const string OnForcedReconnect = "ForcedReconnect";
public const string OnUpdateOrAddBannedUser = "UpdateOrAddBannedUser";
public const string OnDeleteBannedUser = "DeleteBannedUser";
public const string OnUpdateOrAddForbiddenFile = "UpdateOrAddForbiddenFile";
public const string OnDeleteForbiddenFile = "DeleteForbiddenFile";
}
public const string InvokeUserGetOnlineUsers = "GetOnlineUsers";
public const string InvokeUserRegister = "Register";
public const string InvokeUserPushCharacterDataToVisibleClients = "PushCharacterDataToVisibleClients";
public const string InvokeUserGetOnlineCharacters = "GetOnlineCharacters";
public const string SendUserPairedClientAddition = "SendPairedClientAddition";
public const string SendUserPairedClientRemoval = "SendPairedClientRemoval";
public const string SendUserPairedClientPauseChange = "SendPairedClientPauseChange";
public const string InvokeUserGetPairedClients = "GetPairedClients";
public const string SendUserDeleteAccount = "DeleteAccount";
public class UserHubAPI
{
public const string Path = "/user";
public const string InvokeGetOnlineUsers = "GetOnlineUsers";
public const string InvokeRegister = "Register";
public const string InvokePushCharacterDataToVisibleClients = "PushCharacterDataToVisibleClients";
public const string InvokeGetOnlineCharacters = "GetOnlineCharacters";
public const string SendPairedClientAddition = "SendPairedClientAddition";
public const string SendPairedClientRemoval = "SendPairedClientRemoval";
public const string SendPairedClientPauseChange = "SendPairedClientPauseChange";
public const string InvokeGetPairedClients = "GetPairedClients";
public const string SendDeleteAccount = "DeleteAccount";
public const string OnUpdateClientPairs = "UpdateClientPairs";
public const string OnReceiveCharacterData = "ReceiveCharacterData";
public const string OnRemoveOnlinePairedPlayer = "RemoveOnlinePairedPlayer";
public const string OnAddOnlinePairedPlayer = "AddOnlinePairedPlayer";
public const string OnUserUpdateClientPairs = "UpdateClientPairs";
public const string OnUserReceiveCharacterData = "ReceiveCharacterData";
public const string OnUserRemoveOnlinePairedPlayer = "RemoveOnlinePairedPlayer";
public const string OnUserAddOnlinePairedPlayer = "AddOnlinePairedPlayer";
}
}

View File

@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
@@ -32,7 +30,8 @@ namespace MareSynchronosServer.Authentication
using var sha256 = SHA256.Create();
var hashedHeader = BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(authHeader))).Replace("-", "");
var uid = (await _mareDbContext.Users.AsNoTracking().FirstOrDefaultAsync(m => m.SecretKey == hashedHeader))?.UID;
var uid = (await _mareDbContext.Auth.Include("User").AsNoTracking()
.FirstOrDefaultAsync(m => m.HashedKey == hashedHeader))?.UserUID;
if (uid == null)
{

View File

@@ -1,8 +1,5 @@
using System.Collections.Generic;
using MareSynchronos.API;
using MareSynchronosServer.Models;
using MareSynchronosServer.Models;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
namespace MareSynchronosServer.Data
{
@@ -17,12 +14,16 @@ namespace MareSynchronosServer.Data
public DbSet<ClientPair> ClientPairs { get; set; }
public DbSet<ForbiddenUploadEntry> ForbiddenUploadEntries { get; set; }
public DbSet<Banned> BannedUsers { get; set; }
public DbSet<Auth> Auth { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Auth>().ToTable("Auth");
modelBuilder.Entity<User>().ToTable("Users");
modelBuilder.Entity<User>().HasIndex(c => c.CharacterIdentification);
modelBuilder.Entity<FileCache>().ToTable("FileCaches");
modelBuilder.Entity<FileCache>().HasIndex(c => c.UploaderUID);
modelBuilder.Entity<ClientPair>().ToTable("ClientPairs");
modelBuilder.Entity<ClientPair>().HasKey(u => new { u.UserUID, u.OtherUserUID });
modelBuilder.Entity<ClientPair>().HasIndex(c => c.UserUID);

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View 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);
}
}
}

View File

@@ -24,7 +24,6 @@ namespace MareSynchronosServer.Migrations
name: "Id",
table: "ClientPairs");
migrationBuilder.AlterColumn<string>(
name: "UserUID",
table: "ClientPairs",

View File

@@ -0,0 +1,197 @@
// <auto-generated />
using System;
using MareSynchronosServer.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace MareSynchronosServer.Migrations
{
[DbContext(typeof(MareDbContext))]
[Migration("20220713083057_MoveAuthToSeparateTable")]
partial class MoveAuthToSeparateTable
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.6")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1);
modelBuilder.Entity("MareSynchronosServer.Models.Auth", b =>
{
b.Property<string>("HashedKey")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("UserUID")
.HasColumnType("nvarchar(10)");
b.HasKey("HashedKey");
b.HasIndex("UserUID");
b.ToTable("Auth", (string)null);
});
modelBuilder.Entity("MareSynchronosServer.Models.Banned", b =>
{
b.Property<string>("CharacterIdentification")
.HasColumnType("nvarchar(450)");
b.Property<string>("Reason")
.HasColumnType("nvarchar(max)");
b.Property<byte[]>("Timestamp")
.IsConcurrencyToken()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
b.HasKey("CharacterIdentification");
b.ToTable("BannedUsers", (string)null);
});
modelBuilder.Entity("MareSynchronosServer.Models.ClientPair", b =>
{
b.Property<string>("UserUID")
.HasMaxLength(10)
.HasColumnType("nvarchar(10)");
b.Property<string>("OtherUserUID")
.HasMaxLength(10)
.HasColumnType("nvarchar(10)");
b.Property<bool>("AllowReceivingMessages")
.HasColumnType("bit");
b.Property<bool>("IsPaused")
.HasColumnType("bit");
b.Property<byte[]>("Timestamp")
.IsConcurrencyToken()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
b.HasKey("UserUID", "OtherUserUID");
b.HasIndex("OtherUserUID");
b.HasIndex("UserUID");
b.ToTable("ClientPairs", (string)null);
});
modelBuilder.Entity("MareSynchronosServer.Models.FileCache", b =>
{
b.Property<string>("Hash")
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<byte[]>("Timestamp")
.IsConcurrencyToken()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
b.Property<bool>("Uploaded")
.HasColumnType("bit");
b.Property<string>("UploaderUID")
.HasColumnType("nvarchar(10)");
b.HasKey("Hash");
b.HasIndex("UploaderUID");
b.ToTable("FileCaches", (string)null);
});
modelBuilder.Entity("MareSynchronosServer.Models.ForbiddenUploadEntry", b =>
{
b.Property<string>("Hash")
.HasColumnType("nvarchar(450)");
b.Property<string>("ForbiddenBy")
.HasColumnType("nvarchar(max)");
b.Property<byte[]>("Timestamp")
.IsConcurrencyToken()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
b.HasKey("Hash");
b.ToTable("ForbiddenUploadEntries", (string)null);
});
modelBuilder.Entity("MareSynchronosServer.Models.User", b =>
{
b.Property<string>("UID")
.HasMaxLength(10)
.HasColumnType("nvarchar(10)");
b.Property<string>("CharacterIdentification")
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsAdmin")
.HasColumnType("bit");
b.Property<bool>("IsModerator")
.HasColumnType("bit");
b.Property<byte[]>("Timestamp")
.IsConcurrencyToken()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
b.HasKey("UID");
b.ToTable("Users", (string)null);
});
modelBuilder.Entity("MareSynchronosServer.Models.Auth", b =>
{
b.HasOne("MareSynchronosServer.Models.User", "User")
.WithMany()
.HasForeignKey("UserUID");
b.Navigation("User");
});
modelBuilder.Entity("MareSynchronosServer.Models.ClientPair", b =>
{
b.HasOne("MareSynchronosServer.Models.User", "OtherUser")
.WithMany()
.HasForeignKey("OtherUserUID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MareSynchronosServer.Models.User", "User")
.WithMany()
.HasForeignKey("UserUID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("OtherUser");
b.Navigation("User");
});
modelBuilder.Entity("MareSynchronosServer.Models.FileCache", b =>
{
b.HasOne("MareSynchronosServer.Models.User", "Uploader")
.WithMany()
.HasForeignKey("UploaderUID");
b.Navigation("Uploader");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,53 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MareSynchronosServer.Migrations
{
public partial class MoveAuthToSeparateTable : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Auth",
columns: table => new
{
HashedKey = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
UserUID = table.Column<string>(type: "nvarchar(10)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Auth", x => x.HashedKey);
table.ForeignKey(
name: "FK_Auth_Users_UserUID",
column: x => x.UserUID,
principalTable: "Users",
principalColumn: "UID");
});
migrationBuilder.Sql("INSERT INTO Auth SELECT SecretKey, UID FROM Users");
migrationBuilder.DropColumn(
name: "SecretKey",
table: "Users");
migrationBuilder.CreateIndex(
name: "IX_Auth_UserUID",
table: "Auth",
column: "UserUID");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Auth");
migrationBuilder.AddColumn<string>(
name: "SecretKey",
table: "Users",
type: "nvarchar(max)",
nullable: true);
}
}
}

View File

@@ -0,0 +1,200 @@
// <auto-generated />
using System;
using MareSynchronosServer.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace MareSynchronosServer.Migrations
{
[DbContext(typeof(MareDbContext))]
[Migration("20220713104127_AddIndexes")]
partial class AddIndexes
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.6")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1);
modelBuilder.Entity("MareSynchronosServer.Models.Auth", b =>
{
b.Property<string>("HashedKey")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("UserUID")
.HasColumnType("nvarchar(10)");
b.HasKey("HashedKey");
b.HasIndex("UserUID");
b.ToTable("Auth", (string)null);
});
modelBuilder.Entity("MareSynchronosServer.Models.Banned", b =>
{
b.Property<string>("CharacterIdentification")
.HasColumnType("nvarchar(450)");
b.Property<string>("Reason")
.HasColumnType("nvarchar(max)");
b.Property<byte[]>("Timestamp")
.IsConcurrencyToken()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
b.HasKey("CharacterIdentification");
b.ToTable("BannedUsers", (string)null);
});
modelBuilder.Entity("MareSynchronosServer.Models.ClientPair", b =>
{
b.Property<string>("UserUID")
.HasMaxLength(10)
.HasColumnType("nvarchar(10)");
b.Property<string>("OtherUserUID")
.HasMaxLength(10)
.HasColumnType("nvarchar(10)");
b.Property<bool>("AllowReceivingMessages")
.HasColumnType("bit");
b.Property<bool>("IsPaused")
.HasColumnType("bit");
b.Property<byte[]>("Timestamp")
.IsConcurrencyToken()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
b.HasKey("UserUID", "OtherUserUID");
b.HasIndex("OtherUserUID");
b.HasIndex("UserUID");
b.ToTable("ClientPairs", (string)null);
});
modelBuilder.Entity("MareSynchronosServer.Models.FileCache", b =>
{
b.Property<string>("Hash")
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<byte[]>("Timestamp")
.IsConcurrencyToken()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
b.Property<bool>("Uploaded")
.HasColumnType("bit");
b.Property<string>("UploaderUID")
.HasColumnType("nvarchar(10)");
b.HasKey("Hash");
b.HasIndex("UploaderUID");
b.ToTable("FileCaches", (string)null);
});
modelBuilder.Entity("MareSynchronosServer.Models.ForbiddenUploadEntry", b =>
{
b.Property<string>("Hash")
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<string>("ForbiddenBy")
.HasColumnType("nvarchar(max)");
b.Property<byte[]>("Timestamp")
.IsConcurrencyToken()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
b.HasKey("Hash");
b.ToTable("ForbiddenUploadEntries", (string)null);
});
modelBuilder.Entity("MareSynchronosServer.Models.User", b =>
{
b.Property<string>("UID")
.HasMaxLength(10)
.HasColumnType("nvarchar(10)");
b.Property<string>("CharacterIdentification")
.HasColumnType("nvarchar(450)");
b.Property<bool>("IsAdmin")
.HasColumnType("bit");
b.Property<bool>("IsModerator")
.HasColumnType("bit");
b.Property<byte[]>("Timestamp")
.IsConcurrencyToken()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
b.HasKey("UID");
b.HasIndex("CharacterIdentification");
b.ToTable("Users", (string)null);
});
modelBuilder.Entity("MareSynchronosServer.Models.Auth", b =>
{
b.HasOne("MareSynchronosServer.Models.User", "User")
.WithMany()
.HasForeignKey("UserUID");
b.Navigation("User");
});
modelBuilder.Entity("MareSynchronosServer.Models.ClientPair", b =>
{
b.HasOne("MareSynchronosServer.Models.User", "OtherUser")
.WithMany()
.HasForeignKey("OtherUserUID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MareSynchronosServer.Models.User", "User")
.WithMany()
.HasForeignKey("UserUID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("OtherUser");
b.Navigation("User");
});
modelBuilder.Entity("MareSynchronosServer.Models.FileCache", b =>
{
b.HasOne("MareSynchronosServer.Models.User", "Uploader")
.WithMany()
.HasForeignKey("UploaderUID");
b.Navigation("Uploader");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,72 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MareSynchronosServer.Migrations
{
public partial class AddIndexes : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "CharacterIdentification",
table: "Users",
type: "nvarchar(450)",
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(max)",
oldNullable: true);
migrationBuilder.DropPrimaryKey(
name: "PK_ForbiddenUploadEntries",
table: "ForbiddenUploadEntries");
migrationBuilder.AlterColumn<string>(
name: "Hash",
table: "ForbiddenUploadEntries",
type: "nvarchar(40)",
maxLength: 40,
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(450)");
migrationBuilder.AddPrimaryKey(
name: "PK_ForbiddenUploadEntries",
table: "ForbiddenUploadEntries",
column: "Hash");
migrationBuilder.CreateIndex(
name: "IX_Users_CharacterIdentification",
table: "Users",
column: "CharacterIdentification");
migrationBuilder.Sql("ALTER DATABASE CURRENT SET ALLOW_SNAPSHOT_ISOLATION ON", true);
migrationBuilder.Sql("ALTER DATABASE CURRENT SET READ_COMMITTED_SNAPSHOT ON", true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_Users_CharacterIdentification",
table: "Users");
migrationBuilder.AlterColumn<string>(
name: "CharacterIdentification",
table: "Users",
type: "nvarchar(max)",
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(450)",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "Hash",
table: "ForbiddenUploadEntries",
type: "nvarchar(450)",
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(40)",
oldMaxLength: 40);
}
}
}

View File

@@ -22,6 +22,22 @@ namespace MareSynchronosServer.Migrations
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1);
modelBuilder.Entity("MareSynchronosServer.Models.Auth", b =>
{
b.Property<string>("HashedKey")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("UserUID")
.HasColumnType("nvarchar(10)");
b.HasKey("HashedKey");
b.HasIndex("UserUID");
b.ToTable("Auth", (string)null);
});
modelBuilder.Entity("MareSynchronosServer.Models.Banned", b =>
{
b.Property<string>("CharacterIdentification")
@@ -97,7 +113,8 @@ namespace MareSynchronosServer.Migrations
modelBuilder.Entity("MareSynchronosServer.Models.ForbiddenUploadEntry", b =>
{
b.Property<string>("Hash")
.HasColumnType("nvarchar(450)");
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<string>("ForbiddenBy")
.HasColumnType("nvarchar(max)");
@@ -119,7 +136,7 @@ namespace MareSynchronosServer.Migrations
.HasColumnType("nvarchar(10)");
b.Property<string>("CharacterIdentification")
.HasColumnType("nvarchar(max)");
.HasColumnType("nvarchar(450)");
b.Property<bool>("IsAdmin")
.HasColumnType("bit");
@@ -127,9 +144,6 @@ namespace MareSynchronosServer.Migrations
b.Property<bool>("IsModerator")
.HasColumnType("bit");
b.Property<string>("SecretKey")
.HasColumnType("nvarchar(max)");
b.Property<byte[]>("Timestamp")
.IsConcurrencyToken()
.ValueGeneratedOnAddOrUpdate()
@@ -137,21 +151,32 @@ namespace MareSynchronosServer.Migrations
b.HasKey("UID");
b.HasIndex("CharacterIdentification");
b.ToTable("Users", (string)null);
});
modelBuilder.Entity("MareSynchronosServer.Models.Auth", b =>
{
b.HasOne("MareSynchronosServer.Models.User", "User")
.WithMany()
.HasForeignKey("UserUID");
b.Navigation("User");
});
modelBuilder.Entity("MareSynchronosServer.Models.ClientPair", b =>
{
b.HasOne("MareSynchronosServer.Models.User", "OtherUser")
.WithMany()
.HasForeignKey("OtherUserUID")
.OnDelete(DeleteBehavior.NoAction)
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MareSynchronosServer.Models.User", "User")
.WithMany()
.HasForeignKey("UserUID")
.OnDelete(DeleteBehavior.NoAction)
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("OtherUser");

View File

@@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;
namespace MareSynchronosServer.Models
{
public class Auth
{
[Key]
[MaxLength(64)]
public string HashedKey { get; set; }
public string UserUID { get; set; }
public User User { get; set; }
}
}

View File

@@ -1,6 +1,4 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
namespace MareSynchronosServer.Models
{
@@ -9,6 +7,7 @@ namespace MareSynchronosServer.Models
[Key]
[MaxLength(40)]
public string Hash { get; set; }
public string UploaderUID { get; set; }
public User Uploader { get; set; }
public bool Uploaded { get; set; }
[Timestamp]

View File

@@ -5,6 +5,7 @@ namespace MareSynchronosServer.Models
public class ForbiddenUploadEntry
{
[Key]
[MaxLength(40)]
public string Hash { get; set; }
public string ForbiddenBy { get; set; }
[Timestamp]

View File

@@ -1,5 +1,4 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
namespace MareSynchronosServer.Models
{
@@ -8,7 +7,6 @@ namespace MareSynchronosServer.Models
[Key]
[MaxLength(10)]
public string UID { get; set; }
public string SecretKey { get; set; }
public string CharacterIdentification { get; set; }
[Timestamp]
public byte[] Timestamp { get; set; }

View File

@@ -90,19 +90,10 @@ namespace MareSynchronosServer
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ConnectionHub>(ConnectionHubAPI.Path, options =>
endpoints.MapHub<MareHub>(Api.Path, options =>
{
options.Transports = HttpTransportType.WebSockets;
});
endpoints.MapHub<UserHub>(UserHubAPI.Path, options =>
{
options.Transports = HttpTransportType.WebSockets;
});
endpoints.MapHub<AdminHub>(AdminHubAPI.Path, options => options.Transports = HttpTransportType.WebSockets);
endpoints.MapHub<FilesHub>(FilesHubAPI.Path, options =>
{
options.ApplicationMaxBufferSize = long.MaxValue;
options.TransportMaxBufferSize = long.MaxValue;
options.ApplicationMaxBufferSize = 5242880;
options.TransportMaxBufferSize = 5242880;
options.Transports = HttpTransportType.WebSockets;
});
});

View File

@@ -21,12 +21,12 @@ public class SystemInfoService : IHostedService, IDisposable
private readonly ILogger<SystemInfoService> _logger;
private readonly IServiceProvider _services;
private readonly IConfiguration _configuration;
private readonly IHubContext<ConnectionHub> _hubContext;
private readonly IHubContext<MareHub> _hubContext;
private Timer _timer;
public SystemInfoDto SystemInfoDto { get; private set; } = new();
public SystemInfoService(ILogger<SystemInfoService> logger, IServiceProvider services,
IConfiguration configuration, IHubContext<ConnectionHub> hubContext)
IConfiguration configuration, IHubContext<MareHub> hubContext)
{
_logger = logger;
_services = services;
@@ -114,7 +114,7 @@ public class SystemInfoService : IHostedService, IDisposable
UploadedFiles = uploadedFiles
};
_hubContext.Clients.All.SendAsync(ConnectionHubAPI.OnUpdateSystemInfo, SystemInfoDto);
_hubContext.Clients.All.SendAsync(Api.OnUpdateSystemInfo, SystemInfoDto);
_logger.LogInformation($"CPU:{cpuUsage:0.00}%, RAM Used:{(double)usedRAM / 1024 / 1024 / 1024:0.00}GB, Cache:{(double)localCacheSize / 1024 / 1024 / 1024:0.00}GB, Users:{loggedInUsers}, NetworkIn:{totalNetworkIn / 1024 / 1024:0.00}MB/s, NetworkOut:{totalNetworkOut / 1024 / 1024:0.00}MB/s");
}