some cleanup server side, increase api version to 2
This commit is contained in:
73
MareSynchronosServer/MareSynchronos.API/API.cs
Normal file
73
MareSynchronosServer/MareSynchronos.API/API.cs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MareSynchronos.API
|
||||||
|
{
|
||||||
|
public class API
|
||||||
|
{
|
||||||
|
public const int Version = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FilesHubAPI
|
||||||
|
{
|
||||||
|
public const string Path = "/files";
|
||||||
|
|
||||||
|
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 class AdminHubAPI
|
||||||
|
{
|
||||||
|
public const string Path = "/admin";
|
||||||
|
|
||||||
|
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 OnForcedReconnect = "ForcedReconnect";
|
||||||
|
public const string OnUpdateOrAddBannedUser = "UpdateOrAddBannedUser";
|
||||||
|
public const string OnDeleteBannedUser = "DeleteBannedUser";
|
||||||
|
public const string OnUpdateOrAddForbiddenFile = "UpdateOrAddForbiddenFile";
|
||||||
|
public const string OnDeleteForbiddenFile = "DeleteForbiddenFile";
|
||||||
|
}
|
||||||
|
|
||||||
|
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 OnUsersOnline = "UsersOnline";
|
||||||
|
public const string OnUpdateClientPairs = "UpdateClientPairs";
|
||||||
|
public const string OnReceiveCharacterData = "ReceiveCharacterData";
|
||||||
|
public const string OnRemoveOnlinePairedPlayer = "RemoveOnlinePairedPlayer";
|
||||||
|
public const string OnAddOnlinePairedPlayer = "AddOnlinePairedPlayer";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,13 +18,91 @@ namespace MareSynchronosServer.Hubs
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<string> OnlineAdmins => DbContext.Users.Where(u => !string.IsNullOrEmpty(u.CharacterIdentification) && (u.IsModerator || u.IsAdmin))
|
|
||||||
.Select(u => u.UID).ToList();
|
|
||||||
|
|
||||||
private bool IsModerator => DbContext.Users.Single(b => b.UID == AuthenticatedUserId).IsModerator || IsAdmin;
|
|
||||||
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 List<string> OnlineAdmins => DbContext.Users.Where(u => !string.IsNullOrEmpty(u.CharacterIdentification) && (u.IsModerator || u.IsAdmin))
|
||||||
|
.Select(u => u.UID).ToList();
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
|
[HubMethodName(AdminHubAPI.SendChangeModeratorStatus)]
|
||||||
|
public async Task ChangeModeratorStatus(string uid, bool isModerator)
|
||||||
|
{
|
||||||
|
if (!IsAdmin) return;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
|
[HubMethodName(AdminHubAPI.SendDeleteBannedUser)]
|
||||||
|
public async Task DeleteBannedUser(BannedUserDto dto)
|
||||||
|
{
|
||||||
|
if (!IsModerator || string.IsNullOrEmpty(dto.CharacterHash)) return;
|
||||||
|
|
||||||
|
var existingUser =
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
|
[HubMethodName(AdminHubAPI.SendDeleteForbiddenFile)]
|
||||||
|
public async Task DeleteForbiddenFile(ForbiddenFileDto dto)
|
||||||
|
{
|
||||||
|
if (!IsAdmin || string.IsNullOrEmpty(dto.Hash)) return;
|
||||||
|
|
||||||
|
var existingFile =
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
|
[HubMethodName(AdminHubAPI.InvokeGetBannedUsers)]
|
||||||
|
public async Task<List<BannedUserDto>> GetBannedUsers()
|
||||||
|
{
|
||||||
|
if (!IsModerator) return null;
|
||||||
|
|
||||||
|
return await DbContext.BannedUsers.Select(b => new BannedUserDto()
|
||||||
|
{
|
||||||
|
CharacterHash = b.CharacterIdentification,
|
||||||
|
Reason = b.Reason
|
||||||
|
}).ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
|
[HubMethodName(AdminHubAPI.InvokeGetForbiddenFiles)]
|
||||||
|
public async Task<List<ForbiddenFileDto>> GetForbiddenFiles()
|
||||||
|
{
|
||||||
|
if (!IsModerator) return null;
|
||||||
|
|
||||||
|
return await DbContext.ForbiddenUploadEntries.Select(b => new ForbiddenFileDto()
|
||||||
|
{
|
||||||
|
Hash = b.Hash,
|
||||||
|
ForbiddenBy = b.ForbiddenBy
|
||||||
|
}).ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
|
[HubMethodName(AdminHubAPI.InvokeGetOnlineUsers)]
|
||||||
public async Task<List<OnlineUserDto>> GetOnlineUsers()
|
public async Task<List<OnlineUserDto>> GetOnlineUsers()
|
||||||
{
|
{
|
||||||
if (!IsModerator) return null;
|
if (!IsModerator) return null;
|
||||||
@@ -39,18 +117,7 @@ namespace MareSynchronosServer.Hubs
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
public async Task<List<BannedUserDto>> GetBannedUsers()
|
[HubMethodName(AdminHubAPI.SendUpdateOrAddBannedUser)]
|
||||||
{
|
|
||||||
if (!IsModerator) return null;
|
|
||||||
|
|
||||||
return await DbContext.BannedUsers.Select(b => new BannedUserDto()
|
|
||||||
{
|
|
||||||
CharacterHash = b.CharacterIdentification,
|
|
||||||
Reason = b.Reason
|
|
||||||
}).ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
|
||||||
public async Task UpdateOrAddBannedUser(BannedUserDto dto)
|
public async Task UpdateOrAddBannedUser(BannedUserDto dto)
|
||||||
{
|
{
|
||||||
if (!IsModerator || string.IsNullOrEmpty(dto.CharacterHash)) return;
|
if (!IsModerator || string.IsNullOrEmpty(dto.CharacterHash)) return;
|
||||||
@@ -72,45 +139,17 @@ namespace MareSynchronosServer.Hubs
|
|||||||
}
|
}
|
||||||
|
|
||||||
await DbContext.SaveChangesAsync();
|
await DbContext.SaveChangesAsync();
|
||||||
await Clients.Users(OnlineAdmins).SendAsync("UpdateOrAddBannedUser", dto);
|
await Clients.Users(OnlineAdmins).SendAsync(AdminHubAPI.OnUpdateOrAddBannedUser, dto);
|
||||||
var bannedUser =
|
var bannedUser =
|
||||||
await DbContext.Users.SingleOrDefaultAsync(u => u.CharacterIdentification == dto.CharacterHash);
|
await DbContext.Users.SingleOrDefaultAsync(u => u.CharacterIdentification == dto.CharacterHash);
|
||||||
if (bannedUser != null)
|
if (bannedUser != null)
|
||||||
{
|
{
|
||||||
await Clients.User(bannedUser.UID).SendAsync("ForcedReconnect");
|
await Clients.User(bannedUser.UID).SendAsync(AdminHubAPI.OnForcedReconnect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
public async Task DeleteBannedUser(BannedUserDto dto)
|
[HubMethodName(AdminHubAPI.SendUpdateOrAddForbiddenFile)]
|
||||||
{
|
|
||||||
if (!IsModerator || string.IsNullOrEmpty(dto.CharacterHash)) return;
|
|
||||||
|
|
||||||
var existingUser =
|
|
||||||
await DbContext.BannedUsers.SingleOrDefaultAsync(b => b.CharacterIdentification == dto.CharacterHash);
|
|
||||||
if (existingUser == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DbContext.Remove(existingUser);
|
|
||||||
await DbContext.SaveChangesAsync();
|
|
||||||
await Clients.Users(OnlineAdmins).SendAsync("DeleteBannedUser", dto);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
|
||||||
public async Task<List<ForbiddenFileDto>> GetForbiddenFiles()
|
|
||||||
{
|
|
||||||
if (!IsModerator) return null;
|
|
||||||
|
|
||||||
return await DbContext.ForbiddenUploadEntries.Select(b => new ForbiddenFileDto()
|
|
||||||
{
|
|
||||||
Hash = b.Hash,
|
|
||||||
ForbiddenBy = b.ForbiddenBy
|
|
||||||
}).ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
|
||||||
public async Task UpdateOrAddForbiddenFile(ForbiddenFileDto dto)
|
public async Task UpdateOrAddForbiddenFile(ForbiddenFileDto dto)
|
||||||
{
|
{
|
||||||
if (!IsAdmin || string.IsNullOrEmpty(dto.Hash)) return;
|
if (!IsAdmin || string.IsNullOrEmpty(dto.Hash)) return;
|
||||||
@@ -133,39 +172,7 @@ namespace MareSynchronosServer.Hubs
|
|||||||
|
|
||||||
await DbContext.SaveChangesAsync();
|
await DbContext.SaveChangesAsync();
|
||||||
|
|
||||||
await Clients.Users(OnlineAdmins).SendAsync("UpdateOrAddForbiddenFile", dto);
|
await Clients.Users(OnlineAdmins).SendAsync(AdminHubAPI.OnUpdateOrAddForbiddenFile, dto);
|
||||||
}
|
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
|
||||||
public async Task DeleteForbiddenFile(ForbiddenFileDto dto)
|
|
||||||
{
|
|
||||||
if (!IsAdmin || string.IsNullOrEmpty(dto.Hash)) return;
|
|
||||||
|
|
||||||
var existingFile =
|
|
||||||
await DbContext.ForbiddenUploadEntries.SingleOrDefaultAsync(b => b.Hash == dto.Hash);
|
|
||||||
if (existingFile == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DbContext.Remove(existingFile);
|
|
||||||
await DbContext.SaveChangesAsync();
|
|
||||||
await Clients.Users(OnlineAdmins).SendAsync("DeleteForbiddenFile", dto);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
|
||||||
public async Task ChangeModeratorStatus(string uid, bool isModerator)
|
|
||||||
{
|
|
||||||
if (!IsAdmin) return;
|
|
||||||
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("ForcedReconnect");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System.Security.Claims;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MareSynchronos.API;
|
using MareSynchronos.API;
|
||||||
using MareSynchronosServer.Data;
|
using MareSynchronosServer.Data;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
@@ -11,11 +12,11 @@ namespace MareSynchronosServer.Hubs
|
|||||||
{
|
{
|
||||||
public class ConnectionHub : BaseHub<ConnectionHub>
|
public class ConnectionHub : BaseHub<ConnectionHub>
|
||||||
{
|
{
|
||||||
private const int ServerVersion = 1;
|
|
||||||
public ConnectionHub(MareDbContext mareDbContext, ILogger<ConnectionHub> logger) : base(mareDbContext, logger)
|
public ConnectionHub(MareDbContext mareDbContext, ILogger<ConnectionHub> logger) : base(mareDbContext, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HubMethodName(ConnectionHubAPI.InvokeHeartbeat)]
|
||||||
public async Task<ConnectionDto> Heartbeat()
|
public async Task<ConnectionDto> Heartbeat()
|
||||||
{
|
{
|
||||||
var userId = Context.User!.Claims.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value;
|
var userId = Context.User!.Claims.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value;
|
||||||
@@ -27,7 +28,7 @@ namespace MareSynchronosServer.Hubs
|
|||||||
var user = (await DbContext.Users.SingleAsync(u => u.UID == userId));
|
var user = (await DbContext.Users.SingleAsync(u => u.UID == userId));
|
||||||
return new ConnectionDto
|
return new ConnectionDto
|
||||||
{
|
{
|
||||||
ServerVersion = ServerVersion,
|
ServerVersion = API.Version,
|
||||||
UID = userId,
|
UID = userId,
|
||||||
IsModerator = user.IsModerator,
|
IsModerator = user.IsModerator,
|
||||||
IsAdmin = user.IsAdmin
|
IsAdmin = user.IsAdmin
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ using MareSynchronosServer.Authentication;
|
|||||||
using MareSynchronosServer.Data;
|
using MareSynchronosServer.Data;
|
||||||
using MareSynchronosServer.Models;
|
using MareSynchronosServer.Models;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@@ -30,6 +31,7 @@ namespace MareSynchronosServer.Hubs
|
|||||||
private string BasePath => _configuration["CacheDirectory"];
|
private string BasePath => _configuration["CacheDirectory"];
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
|
[HubMethodName(FilesHubAPI.SendAbortUpload)]
|
||||||
public async Task AbortUpload()
|
public async Task AbortUpload()
|
||||||
{
|
{
|
||||||
Logger.LogInformation("User " + AuthenticatedUserId + " aborted upload");
|
Logger.LogInformation("User " + AuthenticatedUserId + " aborted upload");
|
||||||
@@ -40,6 +42,102 @@ namespace MareSynchronosServer.Hubs
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
|
[HubMethodName(FilesHubAPI.SendDeleteAllFiles)]
|
||||||
|
public async Task DeleteAllFiles()
|
||||||
|
{
|
||||||
|
Logger.LogInformation("User " + AuthenticatedUserId + " deleted all their files");
|
||||||
|
|
||||||
|
DbContext.CharacterData.RemoveRange(DbContext.CharacterData.Where(c => c.UserId == AuthenticatedUserId));
|
||||||
|
await DbContext.SaveChangesAsync();
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
|
[HubMethodName(FilesHubAPI.StreamDownloadFileAsync)]
|
||||||
|
public async IAsyncEnumerable<byte[]> DownloadFileAsync(string hash, [EnumeratorCancellation] CancellationToken ct)
|
||||||
|
{
|
||||||
|
Logger.LogInformation("User " + AuthenticatedUserId + " downloading file: " + hash);
|
||||||
|
|
||||||
|
var file = DbContext.Files.SingleOrDefault(f => f.Hash == hash);
|
||||||
|
if (file == null) yield break;
|
||||||
|
file.LastAccessTime = DateTime.Now;
|
||||||
|
DbContext.Update(file);
|
||||||
|
await DbContext.SaveChangesAsync(ct);
|
||||||
|
var chunkSize = 1024 * 512; // 512kb
|
||||||
|
int readByteCount;
|
||||||
|
var buffer = new byte[chunkSize];
|
||||||
|
|
||||||
|
await using var fs = File.Open(Path.Combine(BasePath, hash), FileMode.Open, FileAccess.Read);
|
||||||
|
while ((readByteCount = await fs.ReadAsync(buffer, 0, chunkSize, ct)) > 0)
|
||||||
|
{
|
||||||
|
await Task.Delay(10, ct);
|
||||||
|
yield return readByteCount == chunkSize ? buffer.ToArray() : buffer.Take(readByteCount).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.LogInformation("User " + AuthenticatedUserId + " finished downloading file: " + hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
|
[HubMethodName(FilesHubAPI.InvokeGetFileSize)]
|
||||||
|
public async Task<DownloadFileDto> GetFileSize(string hash)
|
||||||
|
{
|
||||||
|
var file = await DbContext.Files.SingleOrDefaultAsync(f => f.Hash == hash);
|
||||||
|
var forbidden = DbContext.ForbiddenUploadEntries.SingleOrDefault(f => f.Hash == hash);
|
||||||
|
var fileInfo = new FileInfo(Path.Combine(BasePath, hash));
|
||||||
|
long fileSize = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
fileSize = fileInfo.Length;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// file doesn't exist anymore
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = new DownloadFileDto
|
||||||
|
{
|
||||||
|
FileExists = fileInfo.Exists,
|
||||||
|
ForbiddenBy = forbidden?.ForbiddenBy ?? string.Empty,
|
||||||
|
IsForbidden = forbidden != null,
|
||||||
|
Hash = hash,
|
||||||
|
Size = fileSize
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!fileInfo.Exists && file != null)
|
||||||
|
{
|
||||||
|
DbContext.Files.Remove(file);
|
||||||
|
await DbContext.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
|
[HubMethodName(FilesHubAPI.InvokeIsUploadFinished)]
|
||||||
|
public async Task<bool> IsUploadFinished()
|
||||||
|
{
|
||||||
|
var userUid = AuthenticatedUserId;
|
||||||
|
return await DbContext.Files.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)]
|
||||||
public async Task<List<UploadFileDto>> SendFiles(List<string> fileListHashes)
|
public async Task<List<UploadFileDto>> SendFiles(List<string> fileListHashes)
|
||||||
{
|
{
|
||||||
fileListHashes = fileListHashes.Distinct().ToList();
|
fileListHashes = fileListHashes.Distinct().ToList();
|
||||||
@@ -76,13 +174,7 @@ namespace MareSynchronosServer.Hubs
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
public async Task<bool> IsUploadFinished()
|
[HubMethodName(FilesHubAPI.SendUploadFileStreamAsync)]
|
||||||
{
|
|
||||||
var userUid = AuthenticatedUserId;
|
|
||||||
return await DbContext.Files.AnyAsync(f => f.Uploader.UID == userUid && !f.Uploaded);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
|
||||||
public async Task UploadFileStreamAsync(string hash, IAsyncEnumerable<byte[]> fileContent)
|
public async Task UploadFileStreamAsync(string hash, IAsyncEnumerable<byte[]> fileContent)
|
||||||
{
|
{
|
||||||
Logger.LogInformation("User " + AuthenticatedUserId + " uploading file: " + hash);
|
Logger.LogInformation("User " + AuthenticatedUserId + " uploading file: " + hash);
|
||||||
@@ -101,9 +193,9 @@ namespace MareSynchronosServer.Hubs
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
DbContext.Files.Remove(relatedFile);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
DbContext.Files.Remove(relatedFile);
|
||||||
await DbContext.SaveChangesAsync();
|
await DbContext.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@@ -124,6 +216,7 @@ namespace MareSynchronosServer.Hubs
|
|||||||
var computedHashString = BitConverter.ToString(computedHash).Replace("-", "");
|
var computedHashString = BitConverter.ToString(computedHash).Replace("-", "");
|
||||||
if (hash != computedHashString)
|
if (hash != computedHashString)
|
||||||
{
|
{
|
||||||
|
Logger.LogWarning($"Computed file hash was not expected file hash. Computed: {computedHashString}, Expected {hash}");
|
||||||
DbContext.Remove(relatedFile);
|
DbContext.Remove(relatedFile);
|
||||||
await DbContext.SaveChangesAsync();
|
await DbContext.SaveChangesAsync();
|
||||||
return;
|
return;
|
||||||
@@ -135,87 +228,13 @@ namespace MareSynchronosServer.Hubs
|
|||||||
relatedFile.LastAccessTime = DateTime.Now;
|
relatedFile.LastAccessTime = DateTime.Now;
|
||||||
await DbContext.SaveChangesAsync();
|
await DbContext.SaveChangesAsync();
|
||||||
Logger.LogInformation("File " + hash + " added to DB");
|
Logger.LogInformation("File " + hash + " added to DB");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.Write(ex.Message);
|
Logger.LogWarning(ex, "Upload failed");
|
||||||
}
|
DbContext.Remove(relatedFile);
|
||||||
}
|
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
|
||||||
public async Task<DownloadFileDto> GetFileSize(string hash)
|
|
||||||
{
|
|
||||||
var file = await DbContext.Files.SingleOrDefaultAsync(f => f.Hash == hash);
|
|
||||||
var forbidden = DbContext.ForbiddenUploadEntries.SingleOrDefault(f => f.Hash == hash);
|
|
||||||
var fileInfo = new FileInfo(Path.Combine(BasePath, hash));
|
|
||||||
|
|
||||||
var response = new DownloadFileDto
|
|
||||||
{
|
|
||||||
FileExists = file != null,
|
|
||||||
ForbiddenBy = forbidden?.ForbiddenBy ?? string.Empty,
|
|
||||||
IsForbidden = forbidden != null,
|
|
||||||
Hash = hash,
|
|
||||||
Size = fileInfo.Length
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!fileInfo.Exists && file != null)
|
|
||||||
{
|
|
||||||
DbContext.Files.Remove(file);
|
|
||||||
await DbContext.SaveChangesAsync();
|
await DbContext.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
|
||||||
public async IAsyncEnumerable<byte[]> DownloadFileAsync(string hash, [EnumeratorCancellation] CancellationToken ct)
|
|
||||||
{
|
|
||||||
Logger.LogInformation("User " + AuthenticatedUserId + " downloading file: " + hash);
|
|
||||||
|
|
||||||
var file = DbContext.Files.SingleOrDefault(f => f.Hash == hash);
|
|
||||||
if (file == null) yield break;
|
|
||||||
file.LastAccessTime = DateTime.Now;
|
|
||||||
DbContext.Update(file);
|
|
||||||
await DbContext.SaveChangesAsync(ct);
|
|
||||||
var chunkSize = 1024 * 512; // 512kb
|
|
||||||
int readByteCount;
|
|
||||||
var buffer = new byte[chunkSize];
|
|
||||||
|
|
||||||
await using var fs = File.Open(Path.Combine(BasePath, hash), FileMode.Open, FileAccess.Read);
|
|
||||||
while ((readByteCount = await fs.ReadAsync(buffer, 0, chunkSize, ct)) > 0)
|
|
||||||
{
|
|
||||||
await Task.Delay(10, ct);
|
|
||||||
yield return readByteCount == chunkSize ? buffer.ToArray() : buffer.Take(readByteCount).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.LogInformation("User " + AuthenticatedUserId + " finished downloading file: " + hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
|
||||||
public async Task DeleteAllFiles()
|
|
||||||
{
|
|
||||||
Logger.LogInformation("User " + AuthenticatedUserId + " deleted all their files");
|
|
||||||
|
|
||||||
DbContext.CharacterData.RemoveRange(DbContext.CharacterData.Where(c => c.UserId == AuthenticatedUserId));
|
|
||||||
await DbContext.SaveChangesAsync();
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,11 +22,142 @@ namespace MareSynchronosServer.Hubs
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
|
[HubMethodName(UserHubAPI.SendDeleteAccount)]
|
||||||
|
public async Task DeleteAccount()
|
||||||
|
{
|
||||||
|
Logger.LogInformation("User " + AuthenticatedUserId + " deleted their account");
|
||||||
|
|
||||||
|
string userid = AuthenticatedUserId;
|
||||||
|
var userEntry = await DbContext.Users.SingleAsync(u => u.UID == userid);
|
||||||
|
var charData = DbContext.CharacterData.Where(u => u.UserId == userid);
|
||||||
|
DbContext.RemoveRange(charData);
|
||||||
|
await DbContext.SaveChangesAsync();
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
OtherUID = userid,
|
||||||
|
IsRemoved = true
|
||||||
|
}, userEntry.CharacterIdentification);
|
||||||
|
}
|
||||||
|
|
||||||
|
DbContext.RemoveRange(otherPairData);
|
||||||
|
DbContext.Remove(userEntry);
|
||||||
|
await DbContext.SaveChangesAsync();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
|
[HubMethodName(UserHubAPI.InvokeGetOnlineCharacters)]
|
||||||
|
public async Task<List<string>> GetOnlineCharacters()
|
||||||
|
{
|
||||||
|
Logger.LogInformation("User " + AuthenticatedUserId + " requested online characters");
|
||||||
|
|
||||||
|
var ownUser = DbContext.Users.Single(u => u.UID == AuthenticatedUserId);
|
||||||
|
var otherUsers = await DbContext.ClientPairs
|
||||||
|
.Include(u => u.User)
|
||||||
|
.Include(u => u.OtherUser)
|
||||||
|
.Where(w => w.User == ownUser && !w.IsPaused)
|
||||||
|
.Where(w => !string.IsNullOrEmpty(w.OtherUser.CharacterIdentification))
|
||||||
|
.Select(e => e.OtherUser).ToListAsync();
|
||||||
|
var otherEntries = await DbContext.ClientPairs.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.All.SendAsync(UserHubAPI.OnUsersOnline,
|
||||||
|
await DbContext.Users.CountAsync(u => !string.IsNullOrEmpty(u.CharacterIdentification)));
|
||||||
|
return otherEntries.Select(e => e.User.CharacterIdentification).Distinct().ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HubMethodName(UserHubAPI.InvokeGetOnlineUsers)]
|
||||||
public async Task<int> GetOnlineUsers()
|
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)]
|
||||||
|
public async Task<List<ClientPairDto>> GetPairedClients()
|
||||||
|
{
|
||||||
|
string userid = AuthenticatedUserId;
|
||||||
|
var user = GetAuthenticatedUser();
|
||||||
|
return DbContext.ClientPairs
|
||||||
|
.Include(u => u.OtherUser)
|
||||||
|
.Include(u => u.User)
|
||||||
|
.Where(w => w.User.UID == userid)
|
||||||
|
.ToList()
|
||||||
|
.Select(w =>
|
||||||
|
{
|
||||||
|
var otherEntry = OppositeEntry(w.OtherUser.UID);
|
||||||
|
return new ClientPairDto
|
||||||
|
{
|
||||||
|
IsPaused = w.IsPaused,
|
||||||
|
OtherUID = w.OtherUser.UID,
|
||||||
|
IsSynced = otherEntry != null,
|
||||||
|
IsPausedFromOthers = otherEntry?.IsPaused ?? false,
|
||||||
|
};
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task OnDisconnectedAsync(Exception exception)
|
||||||
|
{
|
||||||
|
var user = DbContext.Users.SingleOrDefault(u => u.UID == AuthenticatedUserId);
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
|
Logger.LogInformation("Disconnect from " + AuthenticatedUserId);
|
||||||
|
|
||||||
|
var otherUsers = DbContext.ClientPairs
|
||||||
|
.Include(u => u.User)
|
||||||
|
.Include(u => u.OtherUser)
|
||||||
|
.Where(w => w.User == user && !w.IsPaused)
|
||||||
|
.Where(w => !string.IsNullOrEmpty(w.OtherUser.CharacterIdentification))
|
||||||
|
.Select(e => e.OtherUser).ToList();
|
||||||
|
var otherEntries = DbContext.ClientPairs.Include(u => u.User)
|
||||||
|
.Where(u => otherUsers.Any(e => e == u.User) && u.OtherUser == user && !u.IsPaused).ToList();
|
||||||
|
await Clients.Users(otherEntries.Select(e => e.User.UID)).SendAsync(UserHubAPI.OnRemoveOnlinePairedPlayer, user.CharacterIdentification);
|
||||||
|
|
||||||
|
var outdatedCharacterData = DbContext.CharacterData.Where(v => v.UserId == user.UID);
|
||||||
|
DbContext.RemoveRange(outdatedCharacterData);
|
||||||
|
user.CharacterIdentification = null;
|
||||||
|
await DbContext.SaveChangesAsync();
|
||||||
|
|
||||||
|
await Clients.All.SendAsync("UsersOnline",
|
||||||
|
await DbContext.Users.CountAsync(u => !string.IsNullOrEmpty(u.CharacterIdentification)));
|
||||||
|
}
|
||||||
|
|
||||||
|
await base.OnDisconnectedAsync(exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
|
[HubMethodName(UserHubAPI.InvokePushCharacterDataToVisibleClients)]
|
||||||
|
public async Task PushCharacterDataToVisibleClients(CharacterCacheDto characterCache, List<string> visibleCharacterIds)
|
||||||
|
{
|
||||||
|
Logger.LogInformation("User " + AuthenticatedUserId + " pushing character data to " + visibleCharacterIds.Count + " visible clients");
|
||||||
|
|
||||||
|
var uid = AuthenticatedUserId;
|
||||||
|
var entriesHavingThisUser = DbContext.ClientPairs
|
||||||
|
.Include(w => w.User)
|
||||||
|
.Include(w => w.OtherUser)
|
||||||
|
.Where(w => w.OtherUser.UID == uid && !w.IsPaused
|
||||||
|
&& visibleCharacterIds.Contains(w.User.CharacterIdentification)).ToList();
|
||||||
|
|
||||||
|
foreach (var pair in entriesHavingThisUser)
|
||||||
|
{
|
||||||
|
var ownEntry = DbContext.ClientPairs.SingleOrDefault(w =>
|
||||||
|
w.User.UID == uid && w.OtherUser.UID == pair.User.UID);
|
||||||
|
if (ownEntry == null || ownEntry.IsPaused) continue;
|
||||||
|
await Clients.User(pair.User.UID).SendAsync(UserHubAPI.OnReceiveCharacterData, characterCache,
|
||||||
|
pair.OtherUser.CharacterIdentification);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HubMethodName(UserHubAPI.InvokeRegister)]
|
||||||
public async Task<string> Register()
|
public async Task<string> Register()
|
||||||
{
|
{
|
||||||
using var sha256 = SHA256.Create();
|
using var sha256 = SHA256.Create();
|
||||||
@@ -60,110 +191,14 @@ namespace MareSynchronosServer.Hubs
|
|||||||
return computedHash;
|
return computedHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClientPair OppositeEntry(string otherUID) =>
|
|
||||||
DbContext.ClientPairs.SingleOrDefault(w => w.User.UID == otherUID && w.OtherUser.UID == AuthenticatedUserId);
|
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
|
||||||
public string GetUID()
|
|
||||||
{
|
|
||||||
return AuthenticatedUserId;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
|
||||||
public async Task PushCharacterDataToVisibleClients(CharacterCacheDto characterCache, List<string> visibleCharacterIds)
|
|
||||||
{
|
|
||||||
Logger.LogInformation("User " + AuthenticatedUserId + " pushing character data to " + visibleCharacterIds.Count + " visible clients");
|
|
||||||
|
|
||||||
var uid = AuthenticatedUserId;
|
|
||||||
var entriesHavingThisUser = DbContext.ClientPairs
|
|
||||||
.Include(w => w.User)
|
|
||||||
.Include(w => w.OtherUser)
|
|
||||||
.Where(w => w.OtherUser.UID == uid && !w.IsPaused
|
|
||||||
&& visibleCharacterIds.Contains(w.User.CharacterIdentification)).ToList();
|
|
||||||
|
|
||||||
foreach (var pair in entriesHavingThisUser)
|
|
||||||
{
|
|
||||||
var ownEntry = DbContext.ClientPairs.SingleOrDefault(w =>
|
|
||||||
w.User.UID == uid && w.OtherUser.UID == pair.User.UID);
|
|
||||||
if (ownEntry == null || ownEntry.IsPaused) continue;
|
|
||||||
await Clients.User(pair.User.UID).SendAsync("ReceiveCharacterData", characterCache,
|
|
||||||
pair.OtherUser.CharacterIdentification);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
|
||||||
public async Task PushCharacterData(CharacterCacheDto characterCache, List<string> visibleCharacterIds)
|
|
||||||
{
|
|
||||||
Logger.LogInformation("User " + AuthenticatedUserId + " pushing character data");
|
|
||||||
|
|
||||||
var uid = AuthenticatedUserId;
|
|
||||||
var entriesHavingThisUser = DbContext.ClientPairs
|
|
||||||
.Include(w => w.User)
|
|
||||||
.Include(w => w.OtherUser)
|
|
||||||
.Where(w => w.OtherUser.UID == uid && !w.IsPaused
|
|
||||||
&& visibleCharacterIds.Contains(w.User.CharacterIdentification)).ToList();
|
|
||||||
var existingCharacterData =
|
|
||||||
await DbContext.CharacterData.SingleOrDefaultAsync(s =>
|
|
||||||
s.UserId == uid && s.JobId == characterCache.JobId);
|
|
||||||
|
|
||||||
if (existingCharacterData != null && existingCharacterData.Hash != characterCache.Hash)
|
|
||||||
{
|
|
||||||
existingCharacterData.CharacterCache = characterCache;
|
|
||||||
existingCharacterData.Hash = characterCache.Hash;
|
|
||||||
DbContext.CharacterData.Update(existingCharacterData);
|
|
||||||
await DbContext.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
else if (existingCharacterData == null)
|
|
||||||
{
|
|
||||||
CharacterData data = new CharacterData
|
|
||||||
{
|
|
||||||
UserId = AuthenticatedUserId,
|
|
||||||
CharacterCache = characterCache,
|
|
||||||
Hash = characterCache.Hash,
|
|
||||||
JobId = characterCache.JobId
|
|
||||||
};
|
|
||||||
await DbContext.CharacterData.AddAsync(data);
|
|
||||||
await DbContext.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var pair in entriesHavingThisUser)
|
|
||||||
{
|
|
||||||
var ownEntry = DbContext.ClientPairs.SingleOrDefault(w =>
|
|
||||||
w.User.UID == uid && w.OtherUser.UID == pair.User.UID);
|
|
||||||
if (ownEntry == null || ownEntry.IsPaused) continue;
|
|
||||||
await Clients.User(pair.User.UID).SendAsync("ReceiveCharacterData", characterCache,
|
|
||||||
pair.OtherUser.CharacterIdentification);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
|
||||||
public async Task<List<string>> GetOnlineCharacters()
|
|
||||||
{
|
|
||||||
Logger.LogInformation("User " + AuthenticatedUserId + " requested online characters");
|
|
||||||
|
|
||||||
var ownUser = DbContext.Users.Single(u => u.UID == AuthenticatedUserId);
|
|
||||||
var otherUsers = await DbContext.ClientPairs
|
|
||||||
.Include(u => u.User)
|
|
||||||
.Include(u => u.OtherUser)
|
|
||||||
.Where(w => w.User == ownUser && !w.IsPaused)
|
|
||||||
.Where(w => !string.IsNullOrEmpty(w.OtherUser.CharacterIdentification))
|
|
||||||
.Select(e => e.OtherUser).ToListAsync();
|
|
||||||
var otherEntries = await DbContext.ClientPairs.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("AddOnlinePairedPlayer", ownUser.CharacterIdentification);
|
|
||||||
await Clients.All.SendAsync("UsersOnline",
|
|
||||||
await DbContext.Users.CountAsync(u => !string.IsNullOrEmpty(u.CharacterIdentification)));
|
|
||||||
return otherEntries.Select(e => e.User.CharacterIdentification).Distinct().ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
|
[HubMethodName(UserHubAPI.SendPairedClientAddition)]
|
||||||
public async Task SendPairedClientAddition(string uid)
|
public async Task SendPairedClientAddition(string uid)
|
||||||
{
|
{
|
||||||
if (uid == AuthenticatedUserId) return;
|
if (uid == AuthenticatedUserId) return;
|
||||||
|
uid = uid.Trim();
|
||||||
Logger.LogInformation("User " + AuthenticatedUserId + " added " + uid + " to whitelist");
|
Logger.LogInformation("User " + AuthenticatedUserId + " adding " + uid + " to whitelist");
|
||||||
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.SingleOrDefaultAsync(u => u.UID == uid);
|
var otherUser = await DbContext.Users.SingleOrDefaultAsync(u => u.UID == uid);
|
||||||
var existingEntry =
|
var existingEntry =
|
||||||
@@ -180,7 +215,7 @@ namespace MareSynchronosServer.Hubs
|
|||||||
await DbContext.SaveChangesAsync();
|
await DbContext.SaveChangesAsync();
|
||||||
var otherEntry = OppositeEntry(uid);
|
var otherEntry = OppositeEntry(uid);
|
||||||
await Clients.User(user.UID)
|
await Clients.User(user.UID)
|
||||||
.SendAsync("UpdateClientPairs", new ClientPairDto()
|
.SendAsync(UserHubAPI.OnUpdateClientPairs, new ClientPairDto()
|
||||||
{
|
{
|
||||||
OtherUID = otherUser.UID,
|
OtherUID = otherUser.UID,
|
||||||
IsPaused = false,
|
IsPaused = false,
|
||||||
@@ -192,12 +227,12 @@ namespace MareSynchronosServer.Hubs
|
|||||||
if (!string.IsNullOrEmpty(otherUser.CharacterIdentification))
|
if (!string.IsNullOrEmpty(otherUser.CharacterIdentification))
|
||||||
{
|
{
|
||||||
await Clients.User(user.UID)
|
await Clients.User(user.UID)
|
||||||
.SendAsync("AddOnlinePairedPlayer", otherUser.CharacterIdentification);
|
.SendAsync(UserHubAPI.OnAddOnlinePairedPlayer, otherUser.CharacterIdentification);
|
||||||
await Clients.User(otherUser.UID)
|
await Clients.User(otherUser.UID)
|
||||||
.SendAsync("AddOnlinePairedPlayer", user.CharacterIdentification);
|
.SendAsync(UserHubAPI.OnAddOnlinePairedPlayer, user.CharacterIdentification);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Clients.User(uid).SendAsync("UpdateClientPairs",
|
await Clients.User(uid).SendAsync(UserHubAPI.OnUpdateClientPairs,
|
||||||
new ClientPairDto()
|
new ClientPairDto()
|
||||||
{
|
{
|
||||||
OtherUID = user.UID,
|
OtherUID = user.UID,
|
||||||
@@ -209,46 +244,7 @@ namespace MareSynchronosServer.Hubs
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
public async Task SendPairedClientRemoval(string uid)
|
[HubMethodName(UserHubAPI.SendPairedClientPauseChange)]
|
||||||
{
|
|
||||||
if (uid == AuthenticatedUserId) return;
|
|
||||||
|
|
||||||
Logger.LogInformation("User " + AuthenticatedUserId + " removed " + uid + " from whitelist");
|
|
||||||
var user = await DbContext.Users.SingleAsync(u => u.UID == AuthenticatedUserId);
|
|
||||||
var otherUser = await DbContext.Users.SingleOrDefaultAsync(u => u.UID == uid);
|
|
||||||
if (otherUser == null) return;
|
|
||||||
ClientPair wl =
|
|
||||||
await DbContext.ClientPairs.SingleOrDefaultAsync(w => w.User == user && w.OtherUser == otherUser);
|
|
||||||
if (wl == null) return;
|
|
||||||
DbContext.ClientPairs.Remove(wl);
|
|
||||||
await DbContext.SaveChangesAsync();
|
|
||||||
var otherEntry = OppositeEntry(uid);
|
|
||||||
await Clients.User(user.UID)
|
|
||||||
.SendAsync("UpdateClientPairs", new ClientPairDto()
|
|
||||||
{
|
|
||||||
OtherUID = otherUser.UID,
|
|
||||||
IsRemoved = true
|
|
||||||
}, otherUser.CharacterIdentification);
|
|
||||||
if (otherEntry != null)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(otherUser.CharacterIdentification))
|
|
||||||
{
|
|
||||||
await Clients.User(user.UID)
|
|
||||||
.SendAsync("RemoveOnlinePairedPlayer", otherUser.CharacterIdentification);
|
|
||||||
await Clients.User(otherUser.UID)
|
|
||||||
.SendAsync("RemoveOnlinePairedPlayer", user.CharacterIdentification);
|
|
||||||
}
|
|
||||||
await Clients.User(uid).SendAsync("UpdateClientPairs", new ClientPairDto()
|
|
||||||
{
|
|
||||||
OtherUID = user.UID,
|
|
||||||
IsPaused = otherEntry.IsPaused,
|
|
||||||
IsPausedFromOthers = false,
|
|
||||||
IsSynced = false
|
|
||||||
}, user.CharacterIdentification);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
|
||||||
public async Task SendPairedClientPauseChange(string uid, bool isPaused)
|
public async Task SendPairedClientPauseChange(string uid, bool isPaused)
|
||||||
{
|
{
|
||||||
if (uid == AuthenticatedUserId) return;
|
if (uid == AuthenticatedUserId) return;
|
||||||
@@ -264,7 +260,7 @@ namespace MareSynchronosServer.Hubs
|
|||||||
var otherEntry = OppositeEntry(uid);
|
var otherEntry = OppositeEntry(uid);
|
||||||
|
|
||||||
await Clients.User(user.UID)
|
await Clients.User(user.UID)
|
||||||
.SendAsync("UpdateClientPairs", new ClientPairDto()
|
.SendAsync(UserHubAPI.OnUpdateClientPairs, new ClientPairDto()
|
||||||
{
|
{
|
||||||
OtherUID = otherUser.UID,
|
OtherUID = otherUser.UID,
|
||||||
IsPaused = isPaused,
|
IsPaused = isPaused,
|
||||||
@@ -273,7 +269,7 @@ namespace MareSynchronosServer.Hubs
|
|||||||
}, otherUser.CharacterIdentification);
|
}, otherUser.CharacterIdentification);
|
||||||
if (otherEntry != null)
|
if (otherEntry != null)
|
||||||
{
|
{
|
||||||
await Clients.User(uid).SendAsync("UpdateClientPairs", new ClientPairDto()
|
await Clients.User(uid).SendAsync(UserHubAPI.OnUpdateClientPairs, new ClientPairDto()
|
||||||
{
|
{
|
||||||
OtherUID = user.UID,
|
OtherUID = user.UID,
|
||||||
IsPaused = otherEntry.IsPaused,
|
IsPaused = otherEntry.IsPaused,
|
||||||
@@ -284,85 +280,47 @@ namespace MareSynchronosServer.Hubs
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
||||||
public async Task<List<ClientPairDto>> GetPairedClients()
|
[HubMethodName(UserHubAPI.SendPairedClientRemoval)]
|
||||||
|
public async Task SendPairedClientRemoval(string uid)
|
||||||
{
|
{
|
||||||
string userid = AuthenticatedUserId;
|
if (uid == AuthenticatedUserId) return;
|
||||||
var user = GetAuthenticatedUser();
|
|
||||||
return DbContext.ClientPairs
|
Logger.LogInformation("User " + AuthenticatedUserId + " removed " + uid + " from whitelist");
|
||||||
.Include(u => u.OtherUser)
|
var user = await DbContext.Users.SingleAsync(u => u.UID == AuthenticatedUserId);
|
||||||
.Include(u => u.User)
|
var otherUser = await DbContext.Users.SingleOrDefaultAsync(u => u.UID == uid);
|
||||||
.Where(w => w.User.UID == userid)
|
if (otherUser == null) return;
|
||||||
.ToList()
|
ClientPair wl =
|
||||||
.Select(w =>
|
await DbContext.ClientPairs.SingleOrDefaultAsync(w => w.User == user && w.OtherUser == otherUser);
|
||||||
|
if (wl == null) return;
|
||||||
|
DbContext.ClientPairs.Remove(wl);
|
||||||
|
await DbContext.SaveChangesAsync();
|
||||||
|
var otherEntry = OppositeEntry(uid);
|
||||||
|
await Clients.User(user.UID)
|
||||||
|
.SendAsync(UserHubAPI.OnUpdateClientPairs, new ClientPairDto()
|
||||||
{
|
{
|
||||||
var otherEntry = OppositeEntry(w.OtherUser.UID);
|
OtherUID = otherUser.UID,
|
||||||
return new ClientPairDto
|
IsRemoved = true
|
||||||
{
|
}, otherUser.CharacterIdentification);
|
||||||
IsPaused = w.IsPaused,
|
if (otherEntry != null)
|
||||||
OtherUID = w.OtherUser.UID,
|
|
||||||
IsSynced = otherEntry != null,
|
|
||||||
IsPausedFromOthers = otherEntry?.IsPaused ?? false,
|
|
||||||
};
|
|
||||||
}).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AuthScheme)]
|
|
||||||
public async Task DeleteAccount()
|
|
||||||
{
|
|
||||||
Logger.LogInformation("User " + AuthenticatedUserId + " deleted their account");
|
|
||||||
|
|
||||||
string userid = AuthenticatedUserId;
|
|
||||||
var userEntry = await DbContext.Users.SingleOrDefaultAsync(u => u.UID == userid);
|
|
||||||
var charData = DbContext.CharacterData.Where(u => u.UserId == userid);
|
|
||||||
DbContext.RemoveRange(charData);
|
|
||||||
await DbContext.SaveChangesAsync();
|
|
||||||
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)
|
if (!string.IsNullOrEmpty(otherUser.CharacterIdentification))
|
||||||
.SendAsync("UpdateClientPairs", new ClientPairDto()
|
{
|
||||||
{
|
await Clients.User(user.UID)
|
||||||
OtherUID = userid,
|
.SendAsync(UserHubAPI.OnRemoveOnlinePairedPlayer, otherUser.CharacterIdentification);
|
||||||
IsRemoved = true
|
await Clients.User(otherUser.UID)
|
||||||
}, userEntry.CharacterIdentification);
|
.SendAsync(UserHubAPI.OnRemoveOnlinePairedPlayer, user.CharacterIdentification);
|
||||||
|
}
|
||||||
|
await Clients.User(uid).SendAsync(UserHubAPI.OnUpdateClientPairs, new ClientPairDto()
|
||||||
|
{
|
||||||
|
OtherUID = user.UID,
|
||||||
|
IsPaused = otherEntry.IsPaused,
|
||||||
|
IsPausedFromOthers = false,
|
||||||
|
IsSynced = false
|
||||||
|
}, user.CharacterIdentification);
|
||||||
}
|
}
|
||||||
|
|
||||||
DbContext.RemoveRange(otherPairData);
|
|
||||||
DbContext.Remove(userEntry);
|
|
||||||
await DbContext.SaveChangesAsync();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task OnDisconnectedAsync(Exception exception)
|
private ClientPair OppositeEntry(string otherUID) =>
|
||||||
{
|
DbContext.ClientPairs.SingleOrDefault(w => w.User.UID == otherUID && w.OtherUser.UID == AuthenticatedUserId);
|
||||||
var user = DbContext.Users.SingleOrDefault(u => u.UID == AuthenticatedUserId);
|
|
||||||
if (user != null)
|
|
||||||
{
|
|
||||||
Logger.LogInformation("Disconnect from " + AuthenticatedUserId);
|
|
||||||
|
|
||||||
var otherUsers = DbContext.ClientPairs
|
|
||||||
.Include(u => u.User)
|
|
||||||
.Include(u => u.OtherUser)
|
|
||||||
.Where(w => w.User == user && !w.IsPaused)
|
|
||||||
.Where(w => !string.IsNullOrEmpty(w.OtherUser.CharacterIdentification))
|
|
||||||
.Select(e => e.OtherUser).ToList();
|
|
||||||
var otherEntries = DbContext.ClientPairs.Include(u => u.User)
|
|
||||||
.Where(u => otherUsers.Any(e => e == u.User) && u.OtherUser == user && !u.IsPaused).ToList();
|
|
||||||
await Clients.Users(otherEntries.Select(e => e.User.UID)).SendAsync("RemoveOnlinePairedPlayer", user.CharacterIdentification);
|
|
||||||
|
|
||||||
var outdatedCharacterData = DbContext.CharacterData.Where(v => v.UserId == user.UID);
|
|
||||||
DbContext.RemoveRange(outdatedCharacterData);
|
|
||||||
user.CharacterIdentification = null;
|
|
||||||
await DbContext.SaveChangesAsync();
|
|
||||||
|
|
||||||
await Clients.All.SendAsync("UsersOnline",
|
|
||||||
await DbContext.Users.CountAsync(u => !string.IsNullOrEmpty(u.CharacterIdentification)));
|
|
||||||
}
|
|
||||||
|
|
||||||
await base.OnDisconnectedAsync(exception);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using MareSynchronos.API;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@@ -85,16 +86,16 @@ namespace MareSynchronosServer
|
|||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
app.UseEndpoints(endpoints =>
|
||||||
{
|
{
|
||||||
endpoints.MapHub<ConnectionHub>("/heartbeat", options =>
|
endpoints.MapHub<ConnectionHub>(ConnectionHubAPI.Path, options =>
|
||||||
{
|
{
|
||||||
options.Transports = HttpTransportType.WebSockets;
|
options.Transports = HttpTransportType.WebSockets;
|
||||||
});
|
});
|
||||||
endpoints.MapHub<UserHub>("/user", options =>
|
endpoints.MapHub<UserHub>(UserHubAPI.Path, options =>
|
||||||
{
|
{
|
||||||
options.Transports = HttpTransportType.WebSockets;
|
options.Transports = HttpTransportType.WebSockets;
|
||||||
});
|
});
|
||||||
endpoints.MapHub<AdminHub>("/admin", options => options.Transports = HttpTransportType.WebSockets);
|
endpoints.MapHub<AdminHub>(AdminHubAPI.Path, options => options.Transports = HttpTransportType.WebSockets);
|
||||||
endpoints.MapHub<FilesHub>("/files", options =>
|
endpoints.MapHub<FilesHub>(FilesHubAPI.Path, options =>
|
||||||
{
|
{
|
||||||
options.ApplicationMaxBufferSize = long.MaxValue;
|
options.ApplicationMaxBufferSize = long.MaxValue;
|
||||||
options.TransportMaxBufferSize = long.MaxValue;
|
options.TransportMaxBufferSize = long.MaxValue;
|
||||||
|
|||||||
Reference in New Issue
Block a user