I don't know man, it's just too much

This commit is contained in:
Stanley Dimant
2022-06-19 01:56:42 +02:00
parent f6fbb4c862
commit 2b53c6a824
8 changed files with 381 additions and 93 deletions

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace MareSynchronos.API
{
public class CharacterCacheDto
{
public List<FileReplacementDto> FileReplacements { get; set; } = new();
public string GlamourerData { get; set; }
public string Hash { get; set; }
public int JobId { get; set; }
}
public class FileReplacementDto
{
public string[] GamePaths { get; set; } = Array.Empty<string>();
public string Hash { get; set; }
public string ImcData { get; set; }
}
}

View File

@@ -4,4 +4,8 @@
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
</Project> </Project>

View File

@@ -1,5 +1,8 @@
using MareSynchronosServer.Models; using System.Collections.Generic;
using MareSynchronos.API;
using MareSynchronosServer.Models;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
namespace MareSynchronosServer.Data namespace MareSynchronosServer.Data
{ {
@@ -12,12 +15,24 @@ namespace MareSynchronosServer.Data
public DbSet<User> Users { get; set; } public DbSet<User> Users { get; set; }
public DbSet<FileCache> Files { get; set; } public DbSet<FileCache> Files { get; set; }
public DbSet<Whitelist> Whitelists { get; set; } public DbSet<Whitelist> Whitelists { get; set; }
public DbSet<Visibility> Visibilities { get; set; }
public DbSet<CharacterData> CharacterData { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {
modelBuilder.Entity<User>().ToTable("Users"); modelBuilder.Entity<User>().ToTable("Users");
modelBuilder.Entity<FileCache>().ToTable("FileCaches"); modelBuilder.Entity<FileCache>().ToTable("FileCaches");
modelBuilder.Entity<Whitelist>().ToTable("Whitelists"); modelBuilder.Entity<Whitelist>().ToTable("Whitelists");
modelBuilder.Entity<Visibility>().ToTable("Visibility")
.HasKey(k => new { k.CID, k.OtherCID });
modelBuilder.Entity<CharacterData>()
.Property(b => b.EquipmentData)
.HasConversion(
v => JsonConvert.SerializeObject(v),
v => JsonConvert.DeserializeObject<List<FileReplacementDto>>(v));
modelBuilder.Entity<CharacterData>()
.ToTable("CharacterData")
.HasKey(k => new { k.UserId, k.JobId });
} }
} }
} }

View File

@@ -0,0 +1,61 @@
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography;
using MareSynchronosServer.Data;
using Microsoft.AspNetCore.SignalR;
namespace MareSynchronosServer.Hubs
{
public abstract class BaseHub : Hub
{
protected MareDbContext DbContext { get; init; }
protected BaseHub(MareDbContext context)
{
DbContext = context;
}
protected string AuthenticatedUserId => Context.User?.Claims?.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value ?? "Unknown";
protected Models.User? GetAuthenticatedUser()
{
return DbContext.Users.Single(u => u.UID == AuthenticatedUserId);
}
protected Models.User? GetUserFromCID(string cid)
{
return DbContext.Users.SingleOrDefault(c => c.CharacterIdentification == cid);
}
protected Models.User? GetUserFromUID(string uid)
{
return DbContext.Users.SingleOrDefault(c => c.UID == uid);
}
protected bool IsUserOnline(string uid)
{
return DbContext.Users.Any(c => c.UID == uid && !string.IsNullOrEmpty(c.CharacterIdentification));
}
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

@@ -6,47 +6,53 @@ using System.Linq;
using System.Security.Claims; using System.Security.Claims;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Threading.Tasks; using System.Threading.Tasks;
using MareSynchronos.API;
using MareSynchronosServer.Authentication; 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.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
namespace MareSynchronosServer.Hubs namespace MareSynchronosServer.Hubs
{ {
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)] public class Files : BaseHub
public class Files : Hub
{ {
private readonly MareDbContext _dbContext; public Files(MareDbContext dbContext) : base(dbContext)
public Files(MareDbContext dbContext)
{ {
_dbContext = dbContext;
} }
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)] [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)]
public async Task SendFiles(List<string> fileList) public async Task SendFiles(List<FileReplacementDto> fileList)
{ {
var existingFiles = _dbContext.Files.Where(f => fileList.Contains(f.Hash)).ToList(); var fileListHashes = fileList.Select(x => x.Hash).ToList();
foreach (var file in fileList.Where(f => existingFiles.All(e => e.Hash != f))) var existingFiles = DbContext.Files.Where(f => fileListHashes.Contains(f.Hash)).ToList();
foreach (var file in fileListHashes.Where(f => existingFiles.All(e => e.Hash != f)))
{ {
var userId = Context.User!.Claims.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value ?? "Unknown"; var userId = AuthenticatedUserId;
await _dbContext.Files.AddAsync(new FileCache() await DbContext.Files.AddAsync(new FileCache()
{ {
Hash = file, Hash = file,
LastAccessTime = DateTime.Now, LastAccessTime = DateTime.Now,
Uploaded = false, Uploaded = false,
Uploader = _dbContext.Users.Single(u => u.UID == userId) Uploader = DbContext.Users.Single(u => u.UID == userId)
}); });
await _dbContext.SaveChangesAsync(); await DbContext.SaveChangesAsync();
await Clients.Caller!.SendAsync("FileRequest", file); await Clients.Caller!.SendAsync("FileRequest", file);
} }
} }
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)]
public async Task<bool> IsUploadFinished()
{
var userUid = AuthenticatedUserId;
return await DbContext.Files.AnyAsync(f => f.Uploader.UID == userUid && !f.Uploaded);
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)] [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)]
public async Task<bool> UploadFile(string hash, byte[] file) public async Task<bool> UploadFile(string hash, byte[] file)
{ {
var relatedFile = _dbContext.Files.SingleOrDefault(f => f.Hash == hash); var relatedFile = DbContext.Files.SingleOrDefault(f => f.Hash == hash);
if (relatedFile == null) return false; if (relatedFile == null) return false;
var decodedFile = LZ4.LZ4Codec.Unwrap(file); var decodedFile = LZ4.LZ4Codec.Unwrap(file);
using var sha1 = new SHA1CryptoServiceProvider(); using var sha1 = new SHA1CryptoServiceProvider();
@@ -54,21 +60,31 @@ namespace MareSynchronosServer.Hubs
var computedHashString = BitConverter.ToString(computedHash).Replace("-", ""); var computedHashString = BitConverter.ToString(computedHash).Replace("-", "");
if (hash != computedHashString) if (hash != computedHashString)
{ {
DbContext.Remove(relatedFile);
await DbContext.SaveChangesAsync();
return false; return false;
} }
await File.WriteAllBytesAsync(@"G:\ServerTest\" + hash, file); await File.WriteAllBytesAsync(@"G:\ServerTest\" + hash, file);
relatedFile.Uploaded = true; relatedFile.Uploaded = true;
relatedFile.LastAccessTime = DateTime.Now; relatedFile.LastAccessTime = DateTime.Now;
await _dbContext.SaveChangesAsync(); await DbContext.SaveChangesAsync();
return true; return true;
} }
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)]
public async Task<byte[]> DownloadFile(string hash)
{
var file = DbContext.Files.SingleOrDefault(f => f.Hash == hash);
if (file == null) return Array.Empty<byte>();
return await File.ReadAllBytesAsync(@"G:\ServerTest\" + hash);
}
public override Task OnDisconnectedAsync(Exception exception) public override Task OnDisconnectedAsync(Exception exception)
{ {
var userId = Context.User!.Claims.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value; var userId = AuthenticatedUserId;
var notUploadedFiles = _dbContext.Files.Where(f => !f.Uploaded && f.Uploader.UID == userId).ToList(); var notUploadedFiles = DbContext.Files.Where(f => !f.Uploaded && f.Uploader.UID == userId).ToList();
_dbContext.RemoveRange(notUploadedFiles); DbContext.RemoveRange(notUploadedFiles);
_dbContext.SaveChanges(); DbContext.SaveChanges();
return base.OnDisconnectedAsync(exception); return base.OnDisconnectedAsync(exception);
} }
} }

View File

@@ -1,8 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -16,13 +15,10 @@ using Microsoft.EntityFrameworkCore;
namespace MareSynchronosServer.Hubs namespace MareSynchronosServer.Hubs
{ {
public class User : Hub public class User : BaseHub
{ {
private readonly MareDbContext _dbContext; public User(MareDbContext dbContext) : base(dbContext)
public User(MareDbContext dbContext)
{ {
_dbContext = dbContext;
} }
public async Task<string> Register() public async Task<string> Register()
@@ -39,119 +35,269 @@ namespace MareSynchronosServer.Hubs
while (!hasValidUid) while (!hasValidUid)
{ {
var uid = GenerateRandomString(10); 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; user.UID = uid;
hasValidUid = true; hasValidUid = true;
} }
_dbContext.Users.Add(user); DbContext.Users.Add(user);
await _dbContext.SaveChangesAsync(); await DbContext.SaveChangesAsync();
return computedHash; return computedHash;
} }
private Whitelist OppositeEntry(string otherUID) =>
DbContext.Whitelists.SingleOrDefault(w => w.User.UID == otherUID && w.OtherUser.UID == AuthenticatedUserId);
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)] [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)]
public string GetUID() public string GetUID()
{ {
return Context.User!.Claims.Single(c => c.Type == ClaimTypes.NameIdentifier).Value; return AuthenticatedUserId;
} }
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)] [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)]
public async Task SendWhitelist(List<WhitelistDto> whiteListEntries) public async Task SendVisibilityList(List<string> currentVisibilityList)
{ {
var currentUserId = Context.User!.Claims.Single(c => c.Type == ClaimTypes.NameIdentifier).Value; Stopwatch st = Stopwatch.StartNew();
var user = _dbContext.Users.Single(u => u.UID == currentUserId); var cid = DbContext.Users.Single(u => u.UID == AuthenticatedUserId).CharacterIdentification;
var userWhitelists = _dbContext.Whitelists var visibilities = DbContext.Visibilities.Where(v => v.CID == cid).ToList();
foreach (var visibility in currentVisibilityList.Where(visibility => visibilities.All(v => v.OtherCID != visibility)))
{
await DbContext.Visibilities.AddAsync(new Visibility { CID = cid, OtherCID = visibility });
}
foreach (var visibility in visibilities.Where(v => currentVisibilityList.Contains(v.OtherCID)))
{
DbContext.Visibilities.Remove(visibility);
}
await DbContext.SaveChangesAsync();
st.Stop();
Debug.WriteLine("Visibility update took " + st.Elapsed);
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)]
public async Task GetCharacterData(Dictionary<string, int> visibleCharacterWithJobs)
{
var uid = AuthenticatedUserId;
Dictionary<string, CharacterCacheDto> ret = new();
var whitelistEntriesHavingThisUser = DbContext.Whitelists
.Include(w => w.User) .Include(w => w.User)
.Include(w => w.OtherUser) .Include(w => w.OtherUser)
.Where(w => w.User.UID == currentUserId) .Where(w => w.OtherUser.UID == uid && !w.IsPaused
&& visibleCharacterWithJobs.Keys.Contains(w.User.CharacterIdentification))
.ToList(); .ToList();
foreach (var whitelist in whiteListEntries) foreach (var whiteListEntry in whitelistEntriesHavingThisUser)
{ {
var otherEntry = _dbContext.Whitelists.SingleOrDefault(w => bool isNotPaused = await DbContext.Whitelists.AnyAsync(w =>
w.User.UID == whitelist.OtherUID && w.OtherUser.UID == user.UID); !w.IsPaused && w.User.UID == uid && w.OtherUser.UID == whiteListEntry.User.UID);
if (!isNotPaused) continue;
var dictEntry = visibleCharacterWithJobs[whiteListEntry.User.CharacterIdentification];
var prevEntry = userWhitelists.SingleOrDefault(w => w.OtherUser.UID == whitelist.OtherUID); var cachedChar = await
if (prevEntry != null) DbContext.CharacterData.SingleOrDefaultAsync(c => c.UserId == whiteListEntry.User.UID && c.JobId == dictEntry);
if (cachedChar != null)
{ {
prevEntry.IsPaused = whitelist.IsPaused; await Clients.User(uid).SendAsync("ReceiveCharacterData", cachedChar,
whiteListEntry.User.CharacterIdentification);
} }
else }
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)]
public async Task PushCharacterData(CharacterCacheDto characterCache, List<string> visibleCharacterIds)
{
var uid = AuthenticatedUserId;
var whitelistEntriesHavingThisUser = DbContext.Whitelists
.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.EquipmentData =
characterCache.FileReplacements;
existingCharacterData.Hash = characterCache.Hash;
existingCharacterData.GlamourerData = characterCache.GlamourerData;
DbContext.CharacterData.Update(existingCharacterData);
}
else if (existingCharacterData == null)
{
CharacterData data = new CharacterData
{ {
var otherUser = _dbContext.Users.SingleOrDefault(u => u.UID == whitelist.OtherUID); UserId = AuthenticatedUserId,
if (otherUser != null) EquipmentData = characterCache.FileReplacements,
Hash = characterCache.Hash,
GlamourerData = characterCache.GlamourerData,
JobId = characterCache.JobId
};
await DbContext.CharacterData.AddAsync(data);
}
await DbContext.SaveChangesAsync();
foreach (var whitelistEntry in whitelistEntriesHavingThisUser)
{
var ownEntry = DbContext.Whitelists.SingleOrDefault(w =>
w.User.UID == uid && w.OtherUser.UID == whitelistEntry.User.UID);
if (ownEntry == null || ownEntry.IsPaused) continue;
await Clients.User(whitelistEntry.User.UID).SendAsync("ReceiveCharacterData", characterCache, whitelistEntry.OtherUser.CharacterIdentification);
}
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)]
public async Task SendCharacterNameHash(string characterNameHash)
{
DbContext.Users.Single(u => u.UID == AuthenticatedUserId).CharacterIdentification = characterNameHash;
await DbContext.SaveChangesAsync();
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)]
public async Task SendWhitelistAddition(string uid)
{
var user = await DbContext.Users.SingleAsync(u => u.UID == AuthenticatedUserId);
var otherUser = await DbContext.Users.SingleOrDefaultAsync(u => u.UID == uid);
if (otherUser == null) return;
Whitelist wl = new Whitelist()
{
IsPaused = false,
OtherUser = otherUser,
User = user
};
await DbContext.Whitelists.AddAsync(wl);
await DbContext.SaveChangesAsync();
var otherEntry = OppositeEntry(uid);
await Clients.User(user.UID)
.SendAsync("UpdateWhitelist", new WhitelistDto()
{
OtherUID = otherUser.UID,
IsPaused = false,
IsPausedFromOthers = otherEntry?.IsPaused ?? false,
IsSynced = otherEntry != null
}, otherUser.CharacterIdentification);
if (otherEntry != null)
{
await Clients.User(uid).SendAsync("UpdateWhitelist",
new WhitelistDto()
{ {
Whitelist wl = new Whitelist OtherUID = user.UID,
{ IsPaused = otherEntry.IsPaused,
User = user, IsPausedFromOthers = false,
OtherUser = otherUser, IsSynced = true
IsPaused = whitelist.IsPaused }, user.CharacterIdentification);
};
otherEntry = wl;
await _dbContext.Whitelists.AddAsync(wl);
}
}
if (otherEntry != null)
{
await Clients.User(whitelist.OtherUID).SendAsync("UpdateWhitelist", currentUserId, true,
whitelist.IsPaused);
}
await _dbContext.SaveChangesAsync();
} }
}
foreach (var deletedEntry in userWhitelists.Where(u => whiteListEntries.All(e => e.OtherUID != u.OtherUser.UID)).ToList()) [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)]
public async Task SendWhitelistRemoval(string uid)
{
var user = await DbContext.Users.SingleAsync(u => u.UID == AuthenticatedUserId);
var otherUser = await DbContext.Users.SingleOrDefaultAsync(u => u.UID == uid);
if (otherUser == null) return;
Whitelist wl =
await DbContext.Whitelists.SingleOrDefaultAsync(w => w.User == user && w.OtherUser == otherUser);
DbContext.Whitelists.Remove(wl);
await DbContext.SaveChangesAsync();
var otherEntry = OppositeEntry(uid);
await Clients.User(user.UID)
.SendAsync("UpdateWhitelist", new WhitelistDto()
{
OtherUID = otherUser.UID,
IsPaused = false,
IsPausedFromOthers = otherEntry?.IsPaused ?? false,
IsSynced = otherEntry != null
}, otherUser.CharacterIdentification);
if (otherEntry != null)
{ {
var otherEntry = _dbContext.Whitelists.SingleOrDefault(w => await Clients.User(uid).SendAsync("UpdateWhitelist", new WhitelistDto()
w.User.UID == deletedEntry.OtherUser.UID && w.OtherUser.UID == user.UID);
if (otherEntry != null)
{ {
await Clients.User(otherEntry.User.UID).SendAsync("UpdateWhitelist", currentUserId, false, false); OtherUID = user.UID,
} IsPaused = otherEntry.IsPaused,
IsPausedFromOthers = false,
_dbContext.Whitelists.Remove(deletedEntry); IsSynced = false
}, user.CharacterIdentification);
}
}
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)]
public async Task SendWhitelistPauseChange(string uid, bool isPaused)
{
var user = DbContext.Users.Single(u => u.UID == AuthenticatedUserId);
var otherUser = await DbContext.Users.SingleOrDefaultAsync(u => u.UID == uid);
if (otherUser == null) return;
Whitelist wl =
await DbContext.Whitelists.SingleOrDefaultAsync(w => w.User == user && w.OtherUser == otherUser);
wl.IsPaused = isPaused;
DbContext.Update(wl);
await DbContext.SaveChangesAsync();
var otherEntry = OppositeEntry(uid);
await Clients.User(user.UID)
.SendAsync("UpdateWhitelist", new WhitelistDto()
{
OtherUID = otherUser.UID,
IsPaused = isPaused,
IsPausedFromOthers = otherEntry?.IsPaused ?? false,
IsSynced = otherEntry != null
}, otherUser.CharacterIdentification);
if (otherEntry != null)
{
await Clients.User(uid).SendAsync("UpdateWhitelist", new WhitelistDto()
{
OtherUID = user.UID,
IsPaused = otherEntry.IsPaused,
IsPausedFromOthers = isPaused,
IsSynced = true
}, user.CharacterIdentification);
} }
_dbContext.Whitelists.RemoveRange();
await _dbContext.SaveChangesAsync();
} }
[Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)] [Authorize(AuthenticationSchemes = SecretKeyAuthenticationHandler.AUTH_SCHEME)]
public async Task<List<WhitelistDto>> GetWhitelist() public async Task<List<WhitelistDto>> GetWhitelist()
{ {
string userid = Context.User!.Claims.Single(c => c.Type == ClaimTypes.NameIdentifier).Value; string userid = AuthenticatedUserId;
return _dbContext.Whitelists.Include(u => u.OtherUser).Include(u => u.User).Where(w => w.User.UID == userid) var user = GetAuthenticatedUser();
return DbContext.Whitelists
.Include(u => u.OtherUser)
.Include(u => u.User)
.Where(w => w.User.UID == userid)
.ToList() .ToList()
.Select(w => .Select(w =>
{ {
var otherEntry = _dbContext.Whitelists.SingleOrDefault(a => a.User.UID == w.OtherUser.UID && a.OtherUser.UID == userid); var otherEntry = OppositeEntry(w.OtherUser.UID);
var otherUser = GetUserFromUID(w.OtherUser.UID);
var seesYou = false;
if (otherEntry != null)
{
seesYou = DbContext.Visibilities.Any(v =>
v.CID == otherUser.CharacterIdentification && v.OtherCID == user.CharacterIdentification);
}
return new WhitelistDto return new WhitelistDto
{ {
IsPaused = w.IsPaused, IsPaused = w.IsPaused,
OtherUID = w.OtherUser.UID, OtherUID = w.OtherUser.UID,
IsSynced = otherEntry != null, IsSynced = otherEntry != null,
IsPausedFromOthers = otherEntry?.IsPaused ?? false IsPausedFromOthers = otherEntry?.IsPaused ?? false,
}; };
}).ToList(); }).ToList();
} }
public static string GenerateRandomString(int length, string allowableChars = null)
public override Task OnDisconnectedAsync(Exception exception)
{ {
if (string.IsNullOrEmpty(allowableChars)) var user = DbContext.Users.SingleOrDefault(u => u.UID == AuthenticatedUserId);
allowableChars = @"ABCDEFGHJKLMNPQRSTUVWXYZ0123456789"; if (user != null)
{
var outdatedVisibilities = DbContext.Visibilities.Where(v => v.CID == user.CharacterIdentification);
DbContext.RemoveRange(outdatedVisibilities);
var outdatedCharacterData = DbContext.CharacterData.Where(v => v.UserId == user.UID);
DbContext.RemoveRange(outdatedCharacterData);
user.CharacterIdentification = null;
DbContext.SaveChanges();
}
// Generate random data return base.OnDisconnectedAsync(exception);
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

@@ -0,0 +1,14 @@
using System.Collections.Generic;
using MareSynchronos.API;
namespace MareSynchronosServer.Models
{
public class CharacterData
{
public string UserId { get; set; }
public int JobId { get; set; }
public List<FileReplacementDto> EquipmentData { get; set; }
public string GlamourerData { get; set; }
public string Hash { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
namespace MareSynchronosServer.Models
{
public class Visibility
{
public string CID { get; set; }
public string OtherCID { get; set; }
}
}