migrating to .NET Core 2.0

This commit is contained in:
RaidMax
2018-04-08 01:44:42 -05:00
parent 57fd5fae22
commit fdde7dfdba
121 changed files with 534 additions and 1157 deletions

View File

@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Linq.Expressions;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Database;
using Microsoft.EntityFrameworkCore;
namespace SharedLibraryCore.Services
{
public class AliasService : IEntityService<EFAlias>
{
public async Task<EFAlias> Create(EFAlias entity)
{
throw await Task.FromResult(new Exception());
/*using (var context = new DatabaseContext())
{
var alias = new EFAlias()
{
Active = true,
DateAdded = DateTime.UtcNow,
IPAddress = entity.IPAddress,
Name = entity.Name
};
entity.Link = await context.AliasLinks
.FirstAsync(a => a.AliasLinkId == entity.Link.AliasLinkId);
context.Aliases.Add(entity);
await context.SaveChangesAsync();
return entity;
}*/
}
public Task<EFAlias> CreateProxy()
{
return null;
}
public async Task<EFAlias> Delete(EFAlias entity)
{
using (var context = new DatabaseContext())
{
var alias = context.Aliases
.Single(e => e.AliasId == entity.AliasId);
alias.Active = false;
await context.SaveChangesAsync();
return entity;
}
}
public async Task<IList<EFAlias>> Find(Func<EFAlias, bool> expression)
{
return await Task.Run(() =>
{
using (var context = new DatabaseContext())
return context.Aliases
.AsNoTracking()
.Include(a => a.Link.Children)
.Where(expression)
.ToList();
});
}
public async Task<EFAlias> Get(int entityID)
{
using (var context = new DatabaseContext())
return await context.Aliases
.AsNoTracking()
.SingleOrDefaultAsync(e => e.AliasId == entityID);
}
public Task<EFAlias> GetUnique(long entityProperty)
{
throw new NotImplementedException();
}
public async Task<EFAlias> Update(EFAlias entity)
{
throw await Task.FromResult(new Exception());
/*using (var context = new DatabaseContext())
{
entity = context.Aliases.Attach(entity);
context.Entry(entity).State = EntityState.Modified;
await context.SaveChangesAsync();
return entity;
}*/
}
public async Task<EFAliasLink> CreateLink(EFAliasLink link)
{
using (var context = new DatabaseContext())
{
context.AliasLinks.Add(link);
await context.SaveChangesAsync();
return link;
}
}
}
}

View File

@ -0,0 +1,316 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SharedLibraryCore.Database;
using SharedLibraryCore.Database.Models;
using System.Linq.Expressions;
using SharedLibraryCore.Objects;
using Microsoft.EntityFrameworkCore;
namespace SharedLibraryCore.Services
{
public class ClientService : Interfaces.IEntityService<EFClient>
{
public async Task<EFClient> Create(EFClient entity)
{
using (var context = new DatabaseContext())
{
bool hasExistingAlias = false;
// get all aliases by IP
var aliases = await context.Aliases
.Include(a => a.Link)
.Where(a => a.IPAddress == entity.IPAddress)
.ToListAsync();
// see if they have a matching IP + Name but new NetworkId
var existingAlias = aliases.FirstOrDefault(a => a.Name == entity.Name);
// if existing alias matches link them
EFAliasLink aliasLink = existingAlias?.Link;
// if no exact matches find the first IP that matches
aliasLink = aliasLink ?? aliases.FirstOrDefault()?.Link;
// if no exact or IP matches, create new link
aliasLink = aliasLink ?? new EFAliasLink()
{
Active = true,
};
// this has to be set here because we can't evalute it properly later
hasExistingAlias = existingAlias != null;
// if no existing alias create new alias
existingAlias = existingAlias ?? new EFAlias()
{
Active = true,
DateAdded = DateTime.UtcNow,
IPAddress = entity.IPAddress,
Link = aliasLink,
Name = entity.Name,
};
var client = new EFClient()
{
Active = true,
// set the level to the level of the existing client if they have the same IP + Name but new NetworkId
// fixme: issues?
Level = hasExistingAlias ?
context.Clients.First(c => c.AliasLinkId == existingAlias.LinkId).Level :
Player.Permission.User,
FirstConnection = DateTime.UtcNow,
Connections = 1,
LastConnection = DateTime.UtcNow,
Masked = false,
NetworkId = entity.NetworkId,
AliasLink = aliasLink,
CurrentAlias = existingAlias,
};
context.Clients.Add(client);
await context.SaveChangesAsync();
return client;
}
}
public async Task<EFClient> Delete(EFClient entity)
{
using (var context = new DatabaseContext())
{
var client = context.Clients
.Single(e => e.ClientId == entity.ClientId);
entity.Active = false;
context.Entry(entity).State = EntityState.Modified;
await context.SaveChangesAsync();
return entity;
}
}
public async Task<IList<EFClient>> Find(Func<EFClient, bool> e)
{
return await Task.Run(() =>
{
using (var context = new DatabaseContext())
{
return context.Clients
.AsNoTracking()
.Include(c => c.CurrentAlias)
.Include(c => c.AliasLink.Children)
.Where(e).ToList();
}
});
}
public async Task<EFClient> Get(int entityID)
{
using (var context = new DatabaseContext())
{
return await new DatabaseContext().Clients
.AsNoTracking()
.Include(c => c.CurrentAlias)
.Include(c => c.AliasLink.Children)
.SingleOrDefaultAsync(e => e.ClientId == entityID);
}
}
public async Task<EFClient> GetUnique(long entityAttribute)
{
using (var context = new DatabaseContext())
{
return await context.Clients
.AsNoTracking()
.Include(c => c.CurrentAlias)
.Include(c => c.AliasLink.Children)
.SingleOrDefaultAsync(c => c.NetworkId == (long)entityAttribute);
}
}
public async Task<EFClient> Update(EFClient entity)
{
using (var context = new DatabaseContext())
{
// grab the context version of the entity
var client = context.Clients
.Include(c => c.AliasLink)
.Include(c => c.CurrentAlias)
.Single(e => e.ClientId == entity.ClientId);
// if their level has been changed
if (entity.Level != client.Level)
{
// get all clients that use the same aliasId
var matchingClients = await context.Clients
.Where(c => c.CurrentAliasId == client.CurrentAliasId)
.ToListAsync();
// update all related clients level
matchingClients.ForEach(c => c.Level = (client.Level == Objects.Player.Permission.Banned) ?
client.Level : entity.Level);
}
// their alias has been updated and not yet saved
if (entity.CurrentAlias.AliasId == 0)
{
client.CurrentAlias = new EFAlias()
{
Active = true,
DateAdded = DateTime.UtcNow,
IPAddress = entity.CurrentAlias.IPAddress,
Name = entity.CurrentAlias.Name,
Link = client.AliasLink
};
}
else
{
client.CurrentAliasId = entity.CurrentAliasId;
}
// set remaining non-navigation properties that may have been updated
client.Level = entity.Level;
client.LastConnection = entity.LastConnection;
client.Connections = entity.Connections;
client.FirstConnection = entity.FirstConnection;
client.Masked = entity.Masked;
client.TotalConnectionTime = entity.TotalConnectionTime;
client.Password = entity.Password;
client.PasswordSalt = entity.PasswordSalt;
// update in database
await context.SaveChangesAsync();
// this is set so future updates don't trigger a new alias add
if (entity.CurrentAlias.AliasId == 0)
entity.CurrentAlias.AliasId = client.CurrentAlias.AliasId;
return client;
}
}
#region ServiceSpecific
public async Task<IList<EFClient>> GetOwners()
{
using (var context = new DatabaseContext())
return await context.Clients
.Where(c => c.Level == Objects.Player.Permission.Owner)
.ToListAsync();
}
public async Task<bool> IsAuthenticated(int clientIP)
{
using (var context = new DatabaseContext())
{
var iqMatching = from alias in context.Aliases
where alias.IPAddress == clientIP
join client in context.Clients
on alias.LinkId equals client.AliasLinkId
where client.Level > Player.Permission.Trusted
select client;
return (await iqMatching.CountAsync()) > 0;
}
}
public async Task<IList<EFClient>> GetPrivilegedClients()
{
using (var context = new DatabaseContext())
{
return await new DatabaseContext().Clients
.AsNoTracking()
.Include(c => c.CurrentAlias)
.Where(c => c.Level >= Player.Permission.Trusted)
.ToListAsync();
}
}
public async Task<IList<EFClient>> GetClientByName(string name)
{
using (var context = new DatabaseContext())
{
var iqClients = (from alias in context.Aliases
.AsNoTracking()
where alias.Name
.Contains(name)
join link in context.AliasLinks
on alias.LinkId equals link.AliasLinkId
join client in context.Clients
.AsNoTracking()
on alias.LinkId equals client.AliasLinkId
select client)
.Distinct()
.Include(c => c.CurrentAlias)
.Include(c => c.AliasLink.Children);
return await iqClients.ToListAsync();
}
}
public async Task<IList<EFClient>> GetClientByIP(int ipAddress)
{
using (var context = new DatabaseContext())
{
var iqClients = (from alias in context.Aliases
.AsNoTracking()
where alias.IPAddress == ipAddress
join link in context.AliasLinks
on alias.LinkId equals link.AliasLinkId
join client in context.Clients
.AsNoTracking()
on alias.LinkId equals client.AliasLinkId
select client)
.Distinct()
.Include(c => c.CurrentAlias)
.Include(c => c.AliasLink.Children);
return await iqClients.ToListAsync();
}
}
public async Task<IList<EFClient>> GetRecentClients(int offset, int count)
{
using (var context = new DatabaseContext())
return await context.Clients
.AsNoTracking()
.Include(c => c.CurrentAlias)
.Include(p => p.AliasLink)
.OrderByDescending(p => p.ClientId)
.Skip(offset)
.Take(count)
.ToListAsync();
}
public async Task<IList<EFClient>> PruneInactivePrivilegedClients(int inactiveDays)
{
using (var context = new DatabaseContext())
{
var inactive = await context.Clients.Where(c => c.Level > Objects.Player.Permission.Flagged)
.AsNoTracking()
.Where(c => (DateTime.UtcNow - c.LastConnection).TotalDays >= inactiveDays)
.ToListAsync();
inactive.ForEach(c => c.Level = Objects.Player.Permission.User);
await context.SaveChangesAsync();
return inactive;
}
}
public async Task<int> GetTotalClientsAsync()
{
using (var context = new DatabaseContext())
return await context.Clients
.CountAsync();
}
public Task<EFClient> CreateProxy()
{
throw new NotImplementedException();
}
public async Task<int> GetTotalPlayTime()
{
using (var context = new DatabaseContext())
return await context.Clients.SumAsync(c => c.TotalConnectionTime);
}
#endregion
}
}

View File

@ -0,0 +1,146 @@
using Microsoft.EntityFrameworkCore;
using SharedLibraryCore.Database;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace SharedLibraryCore.Services
{
// https://stackoverflow.com/questions/43677906/crud-operations-with-entityframework-using-generic-type
public class GenericRepository<TEntity> where TEntity : class
{
private dynamic _context;
private DbSet<TEntity> _dbSet;
protected DbContext Context
{
get
{
if (_context == null)
{
_context = new DatabaseContext();
}
return _context;
}
}
protected DbSet<TEntity> DBSet
{
get
{
if (_dbSet == null)
{
_dbSet = this.Context.Set<TEntity>();
}
return _dbSet;
}
}
public virtual async Task<IList<TEntity>> FindAsync(Expression<Func<TEntity, bool>> predicate, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderExpression = null)
{
return await this.GetQuery(predicate, orderExpression).ToListAsync();
}
public virtual IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderExpression = null)
{
return this.GetQuery(predicate, orderExpression).AsEnumerable();
}
public virtual IQueryable<TEntity> GetQuery(Expression<Func<TEntity, bool>> predicate = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderExpression = null)
{
IQueryable<TEntity> qry = this.DBSet;
if (predicate != null)
qry = qry.Where(predicate);
if (orderExpression != null)
return orderExpression(qry);
return qry;
}
public virtual void Insert<T>(T entity) where T : class
{
DbSet<T> dbSet = this.Context.Set<T>();
dbSet.Add(entity);
}
public virtual TEntity Insert(TEntity entity)
{
return DBSet.Add(entity).Entity;
}
public virtual void Update<T>(T entity) where T : class
{
DbSet<T> dbSet = this.Context.Set<T>();
dbSet.Attach(entity);
this.Context.Entry(entity).State = EntityState.Modified;
}
public virtual void Update(TEntity entity)
{
this.Attach(entity);
this.Context.Entry(entity).State = EntityState.Modified;
}
public virtual void Delete<T>(T entity) where T : class
{
DbSet<T> dbSet = this.Context.Set<T>();
if (this.Context.Entry(entity).State == EntityState.Detached)
dbSet.Attach(entity);
dbSet.Remove(entity);
}
public virtual void Delete(TEntity entity)
{
if (this.Context.Entry(entity).State == EntityState.Detached)
this.Attach(entity);
this.DBSet.Remove(entity);
}
public virtual void Delete<T>(object[] id) where T : class
{
DbSet<T> dbSet = this.Context.Set<T>();
T entity = dbSet.Find(id);
dbSet.Attach(entity);
dbSet.Remove(entity);
}
public virtual void Delete(object id)
{
TEntity entity = this.DBSet.Find(id);
this.Delete(entity);
}
public virtual void Attach(TEntity entity)
{
if (this.Context.Entry(entity).State == EntityState.Detached)
this.DBSet.Attach(entity);
}
public virtual void SaveChanges()
{
this.Context.SaveChanges();
}
public virtual Task SaveChangesAsync()
{
return this.Context.SaveChangesAsync();
}
}
}

View File

@ -0,0 +1,25 @@
using SharedLibraryCore.Dtos;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SharedLibraryCore.Services
{
public class MetaService
{
private static List<Func<int, Task<List<ProfileMeta>>>> MetaActions = new List<Func<int, Task<List<ProfileMeta>>>>();
public static void AddMeta(Func<int, Task<List<ProfileMeta>>> metaAction)
{
MetaActions.Add(metaAction);
}
public static async Task<List<ProfileMeta>> GetMeta(int clientId)
{
var meta = new List<ProfileMeta>();
foreach (var action in MetaActions)
meta.AddRange(await action(clientId));
return meta;
}
}
}

View File

@ -0,0 +1,239 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SharedLibraryCore.Database;
using SharedLibraryCore.Database.Models;
using System.Linq.Expressions;
using SharedLibraryCore.Dtos;
using Microsoft.EntityFrameworkCore;
namespace SharedLibraryCore.Services
{
public class PenaltyService : Interfaces.IEntityService<EFPenalty>
{
public async Task<EFPenalty> Create(EFPenalty entity)
{
using (var context = new DatabaseContext())
{
entity.Offender = context.Clients.Single(e => e.ClientId == entity.Offender.ClientId);
entity.Punisher = context.Clients.Single(e => e.ClientId == entity.Punisher.ClientId);
entity.Link = context.AliasLinks.Single(l => l.AliasLinkId == entity.Link.AliasLinkId);
if (entity.Expires == DateTime.MaxValue)
entity.Expires = DateTime.Parse(System.Data.SqlTypes.SqlDateTime.MaxValue.ToString());
// make bans propogate to all aliases
if (entity.Type == Objects.Penalty.PenaltyType.Ban)
{
await context.Clients
.Where(c => c.AliasLinkId == entity.Link.AliasLinkId)
.ForEachAsync(c => c.Level = Objects.Player.Permission.Banned);
}
// make flags propogate to all aliases
else if (entity.Type == Objects.Penalty.PenaltyType.Flag)
{
await context.Clients
.Where(c => c.AliasLinkId == entity.Link.AliasLinkId)
.ForEachAsync(c => c.Level = Objects.Player.Permission.Flagged);
}
context.Penalties.Add(entity);
await context.SaveChangesAsync();
return entity;
}
}
public Task<EFPenalty> CreateProxy()
{
throw new NotImplementedException();
}
public Task<EFPenalty> Delete(EFPenalty entity)
{
throw new NotImplementedException();
}
public async Task<IList<EFPenalty>> Find(Func<EFPenalty, bool> expression)
{
throw await Task.FromResult(new Exception());
/*
return await Task.FromResult(new List<EFPenalty>());
// fixme: this is so slow!
return await Task.Run(() =>
{
using (var context = new DatabaseContext())
return context.Penalties
.Include(p => p.Offender)
.Include(p => p.Punisher)
.Where(expression)
.Where(p => p.Active)
.ToList();
});*/
}
public Task<EFPenalty> Get(int entityID)
{
throw new NotImplementedException();
}
public Task<EFPenalty> GetUnique(long entityProperty)
{
throw new NotImplementedException();
}
public Task<EFPenalty> Update(EFPenalty entity)
{
throw new NotImplementedException();
}
public async Task<IList<EFPenalty>> GetRecentPenalties(int count, int offset)
{
using (var context = new DatabaseContext())
return await context.Penalties
.AsNoTracking()
.Include(p => p.Offender.CurrentAlias)
.Include(p => p.Punisher.CurrentAlias)
.Where(p => p.Active)
.OrderByDescending(p => p.When)
.Skip(offset)
.Take(count)
.ToListAsync();
}
public async Task<IList<EFPenalty>> GetClientPenaltiesAsync(int clientId)
{
using (var context = new DatabaseContext())
return await context.Penalties
.AsNoTracking()
.Where(p => p.OffenderId == clientId)
.Where(p => p.Active)
.Include(p => p.Offender.CurrentAlias)
.Include(p => p.Punisher.CurrentAlias)
.ToListAsync();
}
/// <summary>
/// Get a read-only copy of client penalties
/// </summary>
/// <param name="clientI"></param>
/// <param name="victim">Retreive penalties for clients receiving penalties, other wise given</param>
/// <returns></returns>
public async Task<List<ProfileMeta>> ReadGetClientPenaltiesAsync(int clientId, bool victim = true)
{
using (var context = new DatabaseContext())
{
/*context.Configuration.LazyLoadingEnabled = false;
context.Configuration.ProxyCreationEnabled = false;
context.Configuration.AutoDetectChangesEnabled = false;*/
if (victim)
{
var iqPenalties = from penalty in context.Penalties.AsNoTracking()
where penalty.OffenderId == clientId
join victimClient in context.Clients.AsNoTracking()
on penalty.OffenderId equals victimClient.ClientId
join victimAlias in context.Aliases
on victimClient.CurrentAliasId equals victimAlias.AliasId
join punisherClient in context.Clients
on penalty.PunisherId equals punisherClient.ClientId
join punisherAlias in context.Aliases
on punisherClient.CurrentAliasId equals punisherAlias.AliasId
//orderby penalty.When descending
select new ProfileMeta()
{
Key = "Event.Penalty",
Value = new PenaltyInfo
{
OffenderName = victimAlias.Name,
OffenderId = victimClient.ClientId,
PunisherName = punisherAlias.Name,
PunisherId = penalty.PunisherId,
Offense = penalty.Offense,
Type = penalty.Type.ToString()
},
When = penalty.When,
Sensitive = penalty.Type == Objects.Penalty.PenaltyType.Flag
};
// fixme: is this good and fast?
return await iqPenalties.ToListAsync();
}
else
{
var iqPenalties = from penalty in context.Penalties.AsNoTracking()
where penalty.PunisherId == clientId
join victimClient in context.Clients.AsNoTracking()
on penalty.OffenderId equals victimClient.ClientId
join victimAlias in context.Aliases
on victimClient.CurrentAliasId equals victimAlias.AliasId
join punisherClient in context.Clients
on penalty.PunisherId equals punisherClient.ClientId
join punisherAlias in context.Aliases
on punisherClient.CurrentAliasId equals punisherAlias.AliasId
//orderby penalty.When descending
select new ProfileMeta()
{
Key = "Event.Penalty",
Value = new PenaltyInfo
{
OffenderName = victimAlias.Name,
OffenderId = victimClient.ClientId,
PunisherName = punisherAlias.Name,
PunisherId = penalty.PunisherId,
Offense = penalty.Offense,
Type = penalty.Type.ToString()
},
When = penalty.When
};
// fixme: is this good and fast?
return await iqPenalties.ToListAsync();
}
}
}
public async Task<List<EFPenalty>> GetActivePenaltiesAsync(int aliasId)
{
using (var context = new DatabaseContext())
{
var iqPenalties = from link in context.AliasLinks
where link.AliasLinkId == aliasId
join penalty in context.Penalties
on link.AliasLinkId equals penalty.LinkId
where penalty.Active
select penalty;
return await iqPenalties.ToListAsync();
}
}
public async Task RemoveActivePenalties(int aliasLinkId)
{
using (var context = new DatabaseContext())
{
var now = DateTime.UtcNow;
var penalties = await context.Penalties
.Include(p => p.Link.Children)
.Where(p => p.LinkId == aliasLinkId)
.Where(p => p.Expires > now)
.ToListAsync();
penalties.ForEach(async p =>
{
p.Active = false;
// reset the player levels
if (p.Type == Objects.Penalty.PenaltyType.Ban)
await context.Clients
.Where(c => c.AliasLinkId == p.LinkId)
.ForEachAsync(c => c.Level = Objects.Player.Permission.User);
});
await context.SaveChangesAsync();
}
}
}
}