diff --git a/Application/Application.csproj b/Application/Application.csproj
index 96ae5c360..53334a694 100644
--- a/Application/Application.csproj
+++ b/Application/Application.csproj
@@ -6,7 +6,7 @@
2.2.2
false
RaidMax.IW4MAdmin.Application
- 2.2.5.4
+ 2.2.5.5
RaidMax
Forever None
IW4MAdmin
@@ -31,8 +31,8 @@
true
true
- 2.2.5.4
- 2.2.5.4
+ 2.2.5.5
+ 2.2.5.5
diff --git a/Application/ApplicationManager.cs b/Application/ApplicationManager.cs
index 68e245baa..f81ae7b85 100644
--- a/Application/ApplicationManager.cs
+++ b/Application/ApplicationManager.cs
@@ -7,6 +7,7 @@ using SharedLibraryCore.Commands;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Database;
using SharedLibraryCore.Database.Models;
+using SharedLibraryCore.Dtos;
using SharedLibraryCore.Events;
using SharedLibraryCore.Exceptions;
using SharedLibraryCore.Helpers;
@@ -58,6 +59,7 @@ namespace IW4MAdmin.Application
readonly SemaphoreSlim ProcessingEvent = new SemaphoreSlim(1, 1);
readonly Dictionary Loggers = new Dictionary();
readonly ITokenAuthentication _authenticator;
+ private readonly MetaService _metaService;
private ApplicationManager()
{
@@ -77,6 +79,7 @@ namespace IW4MAdmin.Application
OnServerEvent += OnGameEvent;
OnServerEvent += EventApi.OnGameEvent;
_authenticator = new TokenAuthentication();
+ _metaService = new MetaService();
}
private async void OnGameEvent(object sender, GameEventArgs args)
@@ -384,6 +387,45 @@ namespace IW4MAdmin.Application
}
#endregion
+ #region META
+ async Task> getLastMap(int clientId)
+ {
+ var meta = await _metaService.GetPersistentMeta("LastMapPlayed", new EFClient() { ClientId = clientId });
+
+ return meta == null ? new List() : new List()
+ {
+ new ProfileMeta()
+ {
+ Id = meta.MetaId,
+ Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_LAST_MAP"],
+ Value = meta.Value,
+ Show = true
+ }
+
+ };
+ }
+
+ async Task> getLastServer(int clientId)
+ {
+ var meta = await _metaService.GetPersistentMeta("LastServerPlayed", new EFClient() { ClientId = clientId });
+
+ return meta == null ? new List() : new List()
+ {
+ new ProfileMeta()
+ {
+ Id = meta.MetaId,
+ Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_LAST_SERVER"],
+ Value = meta.Value,
+ Show = true
+ }
+
+ };
+ }
+
+ MetaService.AddRuntimeMeta(getLastMap);
+ MetaService.AddRuntimeMeta(getLastServer);
+ #endregion
+
#region INIT
async Task Init(ServerConfiguration Conf)
{
diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs
index b2afb6acb..916b11423 100644
--- a/Application/IW4MServer.cs
+++ b/Application/IW4MServer.cs
@@ -9,6 +9,7 @@ using SharedLibraryCore.Exceptions;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Localization;
using SharedLibraryCore.Objects;
+using SharedLibraryCore.Services;
using System;
using System.Collections.Generic;
using System.IO;
@@ -199,6 +200,12 @@ namespace IW4MAdmin
else if (E.Type == GameEvent.EventType.PreConnect)
{
+ // we don't want to track bots in the database at all if ignore bots is requested
+ if (E.Origin.IsBot && Manager.GetApplicationSettings().Configuration().IgnoreBots)
+ {
+ return false;
+ }
+
if (Clients[E.Origin.ClientNumber] == null)
{
#if DEBUG == true
@@ -306,6 +313,12 @@ namespace IW4MAdmin
}
}
+ else if (E.Type == GameEvent.EventType.Disconnect)
+ {
+ await new MetaService().AddPersistentMeta("LastMapPlayed", CurrentMap.Alias, E.Origin);
+ await new MetaService().AddPersistentMeta("LastServerPlayed", E.Owner.Hostname, E.Origin);
+ }
+
else if (E.Type == GameEvent.EventType.PreDisconnect)
{
if ((DateTime.UtcNow - SessionStart).TotalSeconds < 30)
diff --git a/Plugins/AutomessageFeed/Configuration.cs b/Plugins/AutomessageFeed/Configuration.cs
index 50719b2c3..0b8052bac 100644
--- a/Plugins/AutomessageFeed/Configuration.cs
+++ b/Plugins/AutomessageFeed/Configuration.cs
@@ -1,8 +1,5 @@
using SharedLibraryCore;
using SharedLibraryCore.Interfaces;
-using System;
-using System.Collections.Generic;
-using System.Text;
namespace AutomessageFeed
{
@@ -10,6 +7,7 @@ namespace AutomessageFeed
{
public bool EnableFeed { get; set; }
public string FeedUrl { get; set; }
+ public int MaxFeedItems { get; set; }
public IBaseConfiguration Generate()
{
@@ -18,6 +16,9 @@ namespace AutomessageFeed
if (EnableFeed)
{
FeedUrl = Utilities.PromptString(Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_AUTOMESSAGEFEED_URL"]);
+ MaxFeedItems = Utilities.PromptInt(Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_AUTOMESSAGEFEED_PROMPT_MAXITEMS"],
+ Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_AUTOMESSAGEFEED_PROMPT_MAXITEMS_DESC"],
+ 0, int.MaxValue, 0);
}
return this;
diff --git a/Plugins/AutomessageFeed/Plugin.cs b/Plugins/AutomessageFeed/Plugin.cs
index e5835b731..56abd3d22 100644
--- a/Plugins/AutomessageFeed/Plugin.cs
+++ b/Plugins/AutomessageFeed/Plugin.cs
@@ -43,7 +43,7 @@ namespace AutomessageFeed
}
}
- if (_currentFeedItem < items.Count)
+ if (_currentFeedItem < items.Count && (_configuration.MaxFeedItems == 0 || _currentFeedItem < _configuration.MaxFeedItems))
{
_currentFeedItem++;
return items[_currentFeedItem - 1];
diff --git a/Plugins/Stats/Plugin.cs b/Plugins/Stats/Plugin.cs
index c9bf5727a..c93ecc53d 100644
--- a/Plugins/Stats/Plugin.cs
+++ b/Plugins/Stats/Plugin.cs
@@ -282,14 +282,14 @@ namespace IW4MAdmin.Plugins.Stats
return messageMeta;
}
- MetaService.AddMeta(getStats);
+ MetaService.AddRuntimeMeta(getStats);
if (Config.Configuration().EnableAntiCheat)
{
- MetaService.AddMeta(getAnticheatInfo);
+ MetaService.AddRuntimeMeta(getAnticheatInfo);
}
- MetaService.AddMeta(getMessages);
+ MetaService.AddRuntimeMeta(getMessages);
async Task totalKills(Server server)
{
diff --git a/Plugins/Tests/Tests.csproj b/Plugins/Tests/Tests.csproj
index 84255c5de..03e7bb2d2 100644
--- a/Plugins/Tests/Tests.csproj
+++ b/Plugins/Tests/Tests.csproj
@@ -13,8 +13,12 @@
-
-
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
diff --git a/SharedLibraryCore/Database/DatabaseContext.cs b/SharedLibraryCore/Database/DatabaseContext.cs
index 98de184bf..e60bbd806 100644
--- a/SharedLibraryCore/Database/DatabaseContext.cs
+++ b/SharedLibraryCore/Database/DatabaseContext.cs
@@ -4,6 +4,7 @@ using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Interfaces;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -22,7 +23,7 @@ namespace SharedLibraryCore.Database
static string _ConnectionString;
static string _provider;
- private static readonly string _migrationPluginDirectory = @"X:\IW4MAdmin\BUILD\Plugins\";
+ private static readonly string _migrationPluginDirectory = @"X:\IW4MAdmin\BUILD\Plugins";
public DatabaseContext(DbContextOptions opt) : base(opt) { }
@@ -123,6 +124,11 @@ namespace SharedLibraryCore.Database
ent.HasIndex(a => a.Name);
});
+ modelBuilder.Entity(ent =>
+ {
+ ent.HasIndex(_meta => _meta.Key);
+ });
+
// force full name for database conversion
modelBuilder.Entity().ToTable("EFClients");
modelBuilder.Entity().ToTable("EFAlias");
@@ -138,7 +144,6 @@ namespace SharedLibraryCore.Database
#endif
IEnumerable directoryFiles = Directory.GetFiles(pluginDir).Where(f => f.EndsWith(".dll"));
-
foreach (string dllPath in directoryFiles)
{
Assembly library;
diff --git a/SharedLibraryCore/Migrations/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs b/SharedLibraryCore/Migrations/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs
new file mode 100644
index 000000000..284f81338
--- /dev/null
+++ b/SharedLibraryCore/Migrations/20190222234742_AddIndexToEFMeta-KeyAndClientId.Designer.cs
@@ -0,0 +1,696 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using SharedLibraryCore.Database;
+
+namespace SharedLibraryCore.Migrations
+{
+ [DbContext(typeof(DatabaseContext))]
+ [Migration("20190222234742_AddIndexToEFMeta-KeyAndClientId")]
+ partial class AddIndexToEFMetaKeyAndClientId
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "2.2.2-servicing-10034");
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
+ {
+ b.Property("SnapshotId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("ClientId");
+
+ b.Property("CurrentSessionLength");
+
+ b.Property("CurrentStrain");
+
+ b.Property("CurrentViewAngleId");
+
+ b.Property("Deaths");
+
+ b.Property("Distance");
+
+ b.Property("EloRating");
+
+ b.Property("HitDestinationId");
+
+ b.Property("HitLocation");
+
+ b.Property("HitOriginId");
+
+ b.Property("HitType");
+
+ b.Property("Hits");
+
+ b.Property("Kills");
+
+ b.Property("LastStrainAngleId");
+
+ b.Property("SessionAngleOffset");
+
+ b.Property("SessionSPM");
+
+ b.Property("SessionScore");
+
+ b.Property("StrainAngleBetween");
+
+ b.Property("TimeSinceLastEvent");
+
+ b.Property("WeaponId");
+
+ b.Property("When");
+
+ b.HasKey("SnapshotId");
+
+ b.HasIndex("ClientId");
+
+ b.HasIndex("CurrentViewAngleId");
+
+ b.HasIndex("HitDestinationId");
+
+ b.HasIndex("HitOriginId");
+
+ b.HasIndex("LastStrainAngleId");
+
+ b.ToTable("EFACSnapshot");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b =>
+ {
+ b.Property("KillId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("AttackerId");
+
+ b.Property("Damage");
+
+ b.Property("DeathOriginVector3Id");
+
+ b.Property("DeathType");
+
+ b.Property("Fraction");
+
+ b.Property("HitLoc");
+
+ b.Property("IsKill");
+
+ b.Property("KillOriginVector3Id");
+
+ b.Property("Map");
+
+ b.Property("ServerId");
+
+ b.Property("VictimId");
+
+ b.Property("ViewAnglesVector3Id");
+
+ b.Property("VisibilityPercentage");
+
+ b.Property("Weapon");
+
+ b.Property("When");
+
+ b.HasKey("KillId");
+
+ b.HasIndex("AttackerId");
+
+ b.HasIndex("DeathOriginVector3Id");
+
+ b.HasIndex("KillOriginVector3Id");
+
+ b.HasIndex("ServerId");
+
+ b.HasIndex("VictimId");
+
+ b.HasIndex("ViewAnglesVector3Id");
+
+ b.ToTable("EFClientKills");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientMessage", b =>
+ {
+ b.Property("MessageId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("ClientId");
+
+ b.Property("Message");
+
+ b.Property("ServerId");
+
+ b.Property("TimeSent");
+
+ b.HasKey("MessageId");
+
+ b.HasIndex("ClientId");
+
+ b.HasIndex("ServerId");
+
+ b.HasIndex("TimeSent");
+
+ b.ToTable("EFClientMessages");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b =>
+ {
+ b.Property("RatingHistoryId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("ClientId");
+
+ b.HasKey("RatingHistoryId");
+
+ b.HasIndex("ClientId");
+
+ b.ToTable("EFClientRatingHistory");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b =>
+ {
+ b.Property("ClientId");
+
+ b.Property("ServerId");
+
+ b.Property("Active");
+
+ b.Property("Deaths");
+
+ b.Property("EloRating");
+
+ b.Property("Kills");
+
+ b.Property("MaxStrain");
+
+ b.Property("RollingWeightedKDR");
+
+ b.Property("SPM");
+
+ b.Property("Skill");
+
+ b.Property("TimePlayed");
+
+ b.Property("VisionAverage");
+
+ b.HasKey("ClientId", "ServerId");
+
+ b.HasIndex("ServerId");
+
+ b.ToTable("EFClientStatistics");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
+ {
+ b.Property("HitLocationCountId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("ClientId")
+ .HasColumnName("EFClientStatistics_ClientId");
+
+ b.Property("HitCount");
+
+ b.Property("HitOffsetAverage");
+
+ b.Property("Location");
+
+ b.Property("MaxAngleDistance");
+
+ b.Property("ServerId")
+ .HasColumnName("EFClientStatistics_ServerId");
+
+ b.HasKey("HitLocationCountId");
+
+ b.HasIndex("ServerId");
+
+ b.HasIndex("ClientId", "ServerId");
+
+ b.ToTable("EFHitLocationCounts");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b =>
+ {
+ b.Property("RatingId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("ActivityAmount");
+
+ b.Property("Newest");
+
+ b.Property("Performance");
+
+ b.Property("Ranking");
+
+ b.Property("RatingHistoryId");
+
+ b.Property("ServerId");
+
+ b.Property("When");
+
+ b.HasKey("RatingId");
+
+ b.HasIndex("Performance");
+
+ b.HasIndex("Ranking");
+
+ b.HasIndex("RatingHistoryId");
+
+ b.HasIndex("ServerId");
+
+ b.HasIndex("When");
+
+ b.ToTable("EFRating");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b =>
+ {
+ b.Property("ServerId");
+
+ b.Property("Active");
+
+ b.Property("EndPoint");
+
+ b.Property("Port");
+
+ b.HasKey("ServerId");
+
+ b.ToTable("EFServers");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b =>
+ {
+ b.Property("StatisticId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("ServerId");
+
+ b.Property("TotalKills");
+
+ b.Property("TotalPlayTime");
+
+ b.HasKey("StatisticId");
+
+ b.HasIndex("ServerId");
+
+ b.ToTable("EFServerStatistics");
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b =>
+ {
+ b.Property("AliasId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("DateAdded");
+
+ b.Property("IPAddress");
+
+ b.Property("LinkId");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(24);
+
+ b.HasKey("AliasId");
+
+ b.HasIndex("IPAddress");
+
+ b.HasIndex("LinkId");
+
+ b.HasIndex("Name");
+
+ b.ToTable("EFAlias");
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b =>
+ {
+ b.Property("AliasLinkId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.HasKey("AliasLinkId");
+
+ b.ToTable("EFAliasLinks");
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b =>
+ {
+ b.Property("ChangeHistoryId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("Comment")
+ .HasMaxLength(128);
+
+ b.Property("CurrentValue");
+
+ b.Property("OriginEntityId");
+
+ b.Property("PreviousValue");
+
+ b.Property("TargetEntityId");
+
+ b.Property("TimeChanged");
+
+ b.Property("TypeOfChange");
+
+ b.HasKey("ChangeHistoryId");
+
+ b.ToTable("EFChangeHistory");
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b =>
+ {
+ b.Property("ClientId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("AliasLinkId");
+
+ b.Property("Connections");
+
+ b.Property("CurrentAliasId");
+
+ b.Property("FirstConnection");
+
+ b.Property("LastConnection");
+
+ b.Property("Level");
+
+ b.Property("Masked");
+
+ b.Property("NetworkId");
+
+ b.Property("Password");
+
+ b.Property("PasswordSalt");
+
+ b.Property("TotalConnectionTime");
+
+ b.HasKey("ClientId");
+
+ b.HasIndex("AliasLinkId");
+
+ b.HasIndex("CurrentAliasId");
+
+ b.HasIndex("NetworkId")
+ .IsUnique();
+
+ b.ToTable("EFClients");
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b =>
+ {
+ b.Property("MetaId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("ClientId");
+
+ b.Property("Created");
+
+ b.Property("Extra");
+
+ b.Property("Key")
+ .IsRequired();
+
+ b.Property("Updated");
+
+ b.Property("Value")
+ .IsRequired();
+
+ b.HasKey("MetaId");
+
+ b.HasIndex("ClientId");
+
+ b.HasIndex("Key");
+
+ b.ToTable("EFMeta");
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b =>
+ {
+ b.Property("PenaltyId")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Active");
+
+ b.Property("AutomatedOffense");
+
+ b.Property("Expires");
+
+ b.Property("IsEvadedOffense");
+
+ b.Property("LinkId");
+
+ b.Property("OffenderId");
+
+ b.Property("Offense")
+ .IsRequired();
+
+ b.Property("PunisherId");
+
+ b.Property("Type");
+
+ b.Property("When");
+
+ b.HasKey("PenaltyId");
+
+ b.HasIndex("LinkId");
+
+ b.HasIndex("OffenderId");
+
+ b.HasIndex("PunisherId");
+
+ b.ToTable("EFPenalties");
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b =>
+ {
+ b.Property("Vector3Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("EFACSnapshotSnapshotId");
+
+ b.Property("X");
+
+ b.Property("Y");
+
+ b.Property("Z");
+
+ b.HasKey("Vector3Id");
+
+ b.HasIndex("EFACSnapshotSnapshotId");
+
+ b.ToTable("Vector3");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
+ .WithMany()
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle")
+ .WithMany()
+ .HasForeignKey("CurrentViewAngleId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination")
+ .WithMany()
+ .HasForeignKey("HitDestinationId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin")
+ .WithMany()
+ .HasForeignKey("HitOriginId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle")
+ .WithMany()
+ .HasForeignKey("LastStrainAngleId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker")
+ .WithMany()
+ .HasForeignKey("AttackerId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("SharedLibraryCore.Helpers.Vector3", "DeathOrigin")
+ .WithMany()
+ .HasForeignKey("DeathOriginVector3Id");
+
+ b.HasOne("SharedLibraryCore.Helpers.Vector3", "KillOrigin")
+ .WithMany()
+ .HasForeignKey("KillOriginVector3Id");
+
+ b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("ServerId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim")
+ .WithMany()
+ .HasForeignKey("VictimId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("SharedLibraryCore.Helpers.Vector3", "ViewAngles")
+ .WithMany()
+ .HasForeignKey("ViewAnglesVector3Id");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientMessage", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
+ .WithMany()
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("ServerId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
+ .WithMany()
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
+ .WithMany()
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("ServerId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
+ .WithMany()
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("ServerId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics")
+ .WithMany("HitLocations")
+ .HasForeignKey("ClientId", "ServerId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b =>
+ {
+ b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory")
+ .WithMany("Ratings")
+ .HasForeignKey("RatingHistoryId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("ServerId");
+ });
+
+ modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b =>
+ {
+ b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
+ .WithMany()
+ .HasForeignKey("ServerId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link")
+ .WithMany("Children")
+ .HasForeignKey("LinkId")
+ .OnDelete(DeleteBehavior.Restrict);
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink")
+ .WithMany()
+ .HasForeignKey("AliasLinkId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias")
+ .WithMany()
+ .HasForeignKey("CurrentAliasId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
+ .WithMany("Meta")
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b =>
+ {
+ b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link")
+ .WithMany("ReceivedPenalties")
+ .HasForeignKey("LinkId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender")
+ .WithMany("ReceivedPenalties")
+ .HasForeignKey("OffenderId")
+ .OnDelete(DeleteBehavior.Restrict);
+
+ b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher")
+ .WithMany("AdministeredPenalties")
+ .HasForeignKey("PunisherId")
+ .OnDelete(DeleteBehavior.Restrict);
+ });
+
+ modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b =>
+ {
+ b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot")
+ .WithMany("PredictedViewAngles")
+ .HasForeignKey("EFACSnapshotSnapshotId");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/SharedLibraryCore/Migrations/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs b/SharedLibraryCore/Migrations/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs
new file mode 100644
index 000000000..2b726c9e0
--- /dev/null
+++ b/SharedLibraryCore/Migrations/20190222234742_AddIndexToEFMeta-KeyAndClientId.cs
@@ -0,0 +1,22 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace SharedLibraryCore.Migrations
+{
+ public partial class AddIndexToEFMetaKeyAndClientId : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateIndex(
+ name: "IX_EFMeta_Key",
+ table: "EFMeta",
+ column: "Key");
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropIndex(
+ name: "IX_EFMeta_Key",
+ table: "EFMeta");
+ }
+ }
+}
diff --git a/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs b/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs
index 19225ca16..2ecfd4260 100644
--- a/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs
+++ b/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs
@@ -14,7 +14,7 @@ namespace SharedLibraryCore.Migrations
{
#pragma warning disable 612, 618
modelBuilder
- .HasAnnotation("ProductVersion", "2.1.4-rtm-31024");
+ .HasAnnotation("ProductVersion", "2.2.2-servicing-10034");
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
{
@@ -443,6 +443,8 @@ namespace SharedLibraryCore.Migrations
b.HasIndex("ClientId");
+ b.HasIndex("Key");
+
b.ToTable("EFMeta");
});
diff --git a/SharedLibraryCore/Services/MetaService.cs b/SharedLibraryCore/Services/MetaService.cs
index e78793f78..2f540185a 100644
--- a/SharedLibraryCore/Services/MetaService.cs
+++ b/SharedLibraryCore/Services/MetaService.cs
@@ -1,24 +1,71 @@
-using SharedLibraryCore.Dtos;
+using Microsoft.EntityFrameworkCore;
+using SharedLibraryCore.Database;
+using SharedLibraryCore.Database.Models;
+using SharedLibraryCore.Dtos;
+using SharedLibraryCore.Interfaces;
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Threading.Tasks;
namespace SharedLibraryCore.Services
{
public class MetaService
{
- private static List>>> MetaActions = new List>>>();
+ private static List>>> _metaActions = new List>>>();
- public static void AddMeta(Func>> metaAction)
+ public async Task AddPersistentMeta(string metaKey, string metaValue, EFClient client)
{
- MetaActions.Add(metaAction);
+ using (var ctx = new DatabaseContext())
+ {
+ var existingMeta = await ctx.EFMeta.FirstOrDefaultAsync(_meta => _meta.ClientId == client.ClientId && _meta.Key == metaKey);
+
+ if (existingMeta != null)
+ {
+ existingMeta.Value = metaValue;
+ existingMeta.Updated = DateTime.UtcNow;
+ }
+
+ else
+ {
+ ctx.EFMeta.Add(new EFMeta()
+ {
+ ClientId = client.ClientId,
+ Created = DateTime.UtcNow,
+ Key = metaKey,
+ Value = metaValue
+ });
+ }
+
+ await ctx.SaveChangesAsync();
+ }
}
- public static async Task> GetMeta(int clientId)
+ public Task GetPersistentMeta(string metaKey, EFClient client)
+ {
+ using (var ctx = new DatabaseContext(disableTracking:true))
+ {
+ return ctx.EFMeta
+ .Where(_meta => _meta.Key == metaKey)
+ .Where(_meta => _meta.ClientId == client.ClientId)
+ .FirstOrDefaultAsync();
+ }
+ }
+
+ public static void AddRuntimeMeta(Func>> metaAction)
+ {
+ _metaActions.Add(metaAction);
+ }
+
+ public static async Task> GetRuntimeMeta(int clientId)
{
var meta = new List();
- foreach (var action in MetaActions)
+
+ foreach (var action in _metaActions)
+ {
meta.AddRange(await action(clientId));
+ }
+
return meta;
}
}
diff --git a/SharedLibraryCore/SharedLibraryCore.csproj b/SharedLibraryCore/SharedLibraryCore.csproj
index 9fb48da62..c4ca779ad 100644
--- a/SharedLibraryCore/SharedLibraryCore.csproj
+++ b/SharedLibraryCore/SharedLibraryCore.csproj
@@ -17,6 +17,7 @@
+
diff --git a/WebfrontCore/Controllers/AccountController.cs b/WebfrontCore/Controllers/AccountController.cs
index 5cfdb3c85..4052070f4 100644
--- a/WebfrontCore/Controllers/AccountController.cs
+++ b/WebfrontCore/Controllers/AccountController.cs
@@ -1,6 +1,5 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
-using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Security.Claims;
@@ -10,6 +9,11 @@ namespace WebfrontCore.Controllers
{
public class AccountController : BaseController
{
+ ///
+ /// life span in months
+ ///
+ private const int COOKIE_LIFESPAN = 3;
+
[HttpGet]
public async Task LoginAsync(int clientId, string password)
{
@@ -22,10 +26,10 @@ namespace WebfrontCore.Controllers
{
var client = Manager.GetPrivilegedClients()[clientId];
- // string[] hashedPassword = await Task.FromResult(SharedLibraryCore.Helpers.Hashing.Hash(password, client.PasswordSalt));
- //if (hashedPassword[0] == client.Password)
+ bool loginSuccess = Manager.TokenAuthenticator.AuthorizeToken(client.NetworkId, password) ||
+ (await Task.FromResult(SharedLibraryCore.Helpers.Hashing.Hash(password, client.PasswordSalt)))[0] == client.Password;
- if (Manager.TokenAuthenticator.AuthorizeToken(client.NetworkId, password))
+ if (loginSuccess)
{
var claims = new[]
{
@@ -40,7 +44,7 @@ namespace WebfrontCore.Controllers
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrinciple, new AuthenticationProperties()
{
AllowRefresh = true,
- ExpiresUtc = DateTime.UtcNow.AddDays(30),
+ ExpiresUtc = DateTime.UtcNow.AddMonths(COOKIE_LIFESPAN),
IsPersistent = true,
IssuedUtc = DateTime.UtcNow
});
diff --git a/WebfrontCore/Controllers/ClientController.cs b/WebfrontCore/Controllers/ClientController.cs
index 8f9365e6c..d012735fe 100644
--- a/WebfrontCore/Controllers/ClientController.cs
+++ b/WebfrontCore/Controllers/ClientController.cs
@@ -59,7 +59,7 @@ namespace WebfrontCore.Controllers
LinkedAccounts = client.LinkedAccounts
};
- var meta = await MetaService.GetMeta(client.ClientId);
+ var meta = await MetaService.GetRuntimeMeta(client.ClientId);
var penaltyMeta = await Manager.GetPenaltyService()
.ReadGetClientPenaltiesAsync(client.ClientId);
var administeredPenaltiesMeta = await Manager.GetPenaltyService()