ed83c4c011
fix bug with unbanned players still showing as banned via lock icon move player based stuff into client class finally renamed Player to EFClient via partial class don't try to run this build because it's in between stages
169 lines
6.1 KiB
C#
169 lines
6.1 KiB
C#
using Microsoft.Data.Sqlite;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using SharedLibraryCore.Database.Models;
|
|
using SharedLibraryCore.Interfaces;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace SharedLibraryCore.Database
|
|
{
|
|
public class DatabaseContext : DbContext
|
|
{
|
|
public DbSet<EFClient> Clients { get; set; }
|
|
public DbSet<EFAlias> Aliases { get; set; }
|
|
public DbSet<EFAliasLink> AliasLinks { get; set; }
|
|
public DbSet<EFPenalty> Penalties { get; set; }
|
|
public DbSet<EFMeta> EFMeta { get; set; }
|
|
public DbSet<EFChangeHistory> EFChangeHistory { get; set; }
|
|
|
|
static string _ConnectionString;
|
|
static string _provider;
|
|
private static string _migrationPluginDirectory = @"X:\IW4MAdmin\BUILD\Plugins\";
|
|
|
|
public DatabaseContext(DbContextOptions<DatabaseContext> opt) : base(opt) { }
|
|
|
|
public DatabaseContext() { }
|
|
|
|
public DatabaseContext(bool disableTracking)
|
|
{
|
|
if (disableTracking)
|
|
{
|
|
this.ChangeTracker.AutoDetectChangesEnabled = false;
|
|
this.ChangeTracker.LazyLoadingEnabled = false;
|
|
this.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
|
}
|
|
}
|
|
|
|
public DatabaseContext(string connStr, string provider)
|
|
{
|
|
_ConnectionString = connStr;
|
|
_provider = provider;
|
|
}
|
|
|
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
|
{
|
|
if (string.IsNullOrEmpty(_ConnectionString))
|
|
{
|
|
string currentPath = Utilities.OperatingDirectory;
|
|
// allows the application to find the database file
|
|
currentPath = !RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
|
|
$"{Path.DirectorySeparatorChar}{currentPath}" :
|
|
currentPath;
|
|
|
|
var connectionStringBuilder = new SqliteConnectionStringBuilder { DataSource = Path.Join(currentPath, "Database", "Database.db") };
|
|
var connectionString = connectionStringBuilder.ToString();
|
|
var connection = new SqliteConnection(connectionString);
|
|
|
|
optionsBuilder.UseSqlite(connection);
|
|
}
|
|
|
|
else
|
|
{
|
|
switch (_provider)
|
|
{
|
|
default:
|
|
case "mysql":
|
|
optionsBuilder.UseMySql(_ConnectionString);
|
|
break;
|
|
case "postgresql":
|
|
optionsBuilder.UseNpgsql(_ConnectionString);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
|
{
|
|
// make network id unique
|
|
modelBuilder.Entity<EFClient>(entity =>
|
|
{
|
|
entity.HasIndex(e => e.NetworkId).IsUnique();
|
|
});
|
|
|
|
modelBuilder.Entity<EFPenalty>(entity =>
|
|
{
|
|
entity.HasOne(p => p.Offender)
|
|
.WithMany(c => c.ReceivedPenalties)
|
|
.HasForeignKey(c => c.OffenderId)
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
|
|
entity.HasOne(p => p.Punisher)
|
|
.WithMany(p => p.AdministeredPenalties)
|
|
.HasForeignKey(c => c.PunisherId)
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
|
|
entity.Property(p => p.Expires)
|
|
.IsRequired(false);
|
|
});
|
|
|
|
modelBuilder.Entity<EFAliasLink>(entity =>
|
|
{
|
|
entity.HasMany(e => e.Children)
|
|
.WithOne(a => a.Link)
|
|
.HasForeignKey(k => k.LinkId)
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
});
|
|
|
|
modelBuilder.Entity<EFAlias>(ent =>
|
|
{
|
|
ent.HasIndex(a => a.IPAddress);
|
|
ent.Property(a => a.Name).HasMaxLength(24);
|
|
ent.HasIndex(a => a.Name);
|
|
});
|
|
|
|
// force full name for database conversion
|
|
modelBuilder.Entity<EFClient>().ToTable("EFClients");
|
|
modelBuilder.Entity<EFAlias>().ToTable("EFAlias");
|
|
modelBuilder.Entity<EFAliasLink>().ToTable("EFAliasLinks");
|
|
modelBuilder.Entity<EFPenalty>().ToTable("EFPenalties");
|
|
|
|
// adapted from
|
|
// https://aleemkhan.wordpress.com/2013/02/28/dynamically-adding-dbset-properties-in-dbcontext-for-entity-framework-code-first/
|
|
string pluginDir = Path.Join(Utilities.OperatingDirectory, "Plugins");
|
|
IEnumerable<string> directoryFiles = Directory.GetFiles(pluginDir).Where(f => f.EndsWith(".dll"));
|
|
|
|
#if DEBUG == TRUE
|
|
foreach (string dllPath in Directory.GetFiles(_migrationPluginDirectory).Where(f => f.EndsWith(".dll")))
|
|
#else
|
|
foreach (string dllPath in directoryFiles)
|
|
#endif
|
|
{
|
|
Assembly library;
|
|
try
|
|
{
|
|
library = Assembly.LoadFrom(dllPath);
|
|
}
|
|
|
|
// not a valid assembly, ie plugin support files
|
|
catch (Exception)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var configurations = library.ExportedTypes.Where(c => c.GetInterfaces().FirstOrDefault(i => typeof(IModelConfiguration).IsAssignableFrom(i)) != null)
|
|
.Select(c => (IModelConfiguration)Activator.CreateInstance(c));
|
|
|
|
foreach (var configurable in configurations)
|
|
{
|
|
configurable.Configure(modelBuilder);
|
|
}
|
|
|
|
foreach (var type in library.ExportedTypes)
|
|
{
|
|
if (type.IsClass && type.IsSubclassOf(typeof(SharedEntity)))
|
|
{
|
|
var method = modelBuilder.GetType().GetMethod("Entity", new[] { typeof(Type) });
|
|
method.Invoke(modelBuilder, new[] { type });
|
|
}
|
|
}
|
|
}
|
|
|
|
base.OnModelCreating(modelBuilder);
|
|
}
|
|
}
|
|
}
|