diff --git a/Application/Manager.cs b/Application/Manager.cs index 60fbb9023..39788bc32 100644 --- a/Application/Manager.cs +++ b/Application/Manager.cs @@ -289,6 +289,7 @@ namespace IW4MAdmin.Application Commands.Add(new CKillServer()); Commands.Add(new CSetPassword()); Commands.Add(new CPing()); + Commands.Add(new CSetGravatar()); foreach (Command C in SharedLibraryCore.Plugins.PluginImporter.ActiveCommands) Commands.Add(C); diff --git a/Plugins/Stats/Cheat/Detection.cs b/Plugins/Stats/Cheat/Detection.cs index 9446a486c..f02ab3747 100644 --- a/Plugins/Stats/Cheat/Detection.cs +++ b/Plugins/Stats/Cheat/Detection.cs @@ -174,7 +174,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat // determine what the max headshot percentage can be for current number of kills double lerpAmount = Math.Min(1.0, (HitCount - Thresholds.LowSampleMinKills) / (double)(/*Thresholds.HighSampleMinKills*/ 60 - Thresholds.LowSampleMinKills)); double maxHeadshotLerpValueForFlag = Thresholds.Lerp(Thresholds.HeadshotRatioThresholdLowSample(2.0), Thresholds.HeadshotRatioThresholdHighSample(2.0), lerpAmount) + marginOfError; - double maxHeadshotLerpValueForBan = Thresholds.Lerp(Thresholds.HeadshotRatioThresholdLowSample(3.0), Thresholds.HeadshotRatioThresholdHighSample(3.0), lerpAmount) + marginOfError; + double maxHeadshotLerpValueForBan = Thresholds.Lerp(Thresholds.HeadshotRatioThresholdLowSample(3.5), Thresholds.HeadshotRatioThresholdHighSample(3.5), lerpAmount) + marginOfError; // determine what the max bone percentage can be for current number of kills double maxBoneRatioLerpValueForFlag = Thresholds.Lerp(Thresholds.BoneRatioThresholdLowSample(2.25), Thresholds.BoneRatioThresholdHighSample(2.25), lerpAmount) + marginOfError; double maxBoneRatioLerpValueForBan = Thresholds.Lerp(Thresholds.BoneRatioThresholdLowSample(3.25), Thresholds.BoneRatioThresholdHighSample(3.25), lerpAmount) + marginOfError; diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs index 350f3bf70..622e66c6f 100644 --- a/SharedLibraryCore/Commands/NativeCommands.cs +++ b/SharedLibraryCore/Commands/NativeCommands.cs @@ -6,6 +6,8 @@ using SharedLibraryCore.Services; using System; using System.Collections.Generic; using System.Linq; +using System.Net; +using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; @@ -1181,4 +1183,65 @@ namespace SharedLibraryCore.Commands } } } + + public class CSetGravatar : Command + { + public CSetGravatar() : base("setgravatar", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_GRAVATAR_DESC"], "sg", Player.Permission.User, false, new CommandArgument[] + { + new CommandArgument() + { + Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_GRAVATAR"], + Required = true + } + }) + { } + + public override async Task ExecuteAsync(GameEvent E) + { + using (var ctx = new DatabaseContext()) + { + var iqMeta = from meta in ctx.EFMeta + where meta.ClientId == E.Origin.ClientId + where meta.Key == "GravatarEmail" + select meta; + + var gravatarMeta = await iqMeta.FirstOrDefaultAsync(); + + // gravatar meta has never been added + if (gravatarMeta == null) + { + using (var md5 = MD5.Create()) + { + gravatarMeta = new EFMeta() + { + Active = true, + ClientId = E.Origin.ClientId, + Key = "GravatarEmail", + Value = string.Concat(md5.ComputeHash(E.Data.ToLower().Select(d => Convert.ToByte(d)).ToArray()) + .Select(h => h.ToString("x2"))), + }; + + ctx.EFMeta.Add(gravatarMeta); + await ctx.SaveChangesAsync(); + await E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_GRAVATAR_SUCCESS_NEW"]); + return; + } + } + + else + { + ctx.EFMeta.Update(gravatarMeta); + using (var md5 = MD5.Create()) + { + gravatarMeta.Value = string.Concat(md5.ComputeHash(E.Data.ToLower().Select(d => Convert.ToByte(d)).ToArray()) + .Select(h => h.ToString("x2"))); + gravatarMeta.Updated = DateTime.UtcNow; + } + + await ctx.SaveChangesAsync(); + await E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_GRAVATAR_SUCCESS_UPDATE"]); + } + } + } + } } diff --git a/SharedLibraryCore/Database/DatabaseContext.cs b/SharedLibraryCore/Database/DatabaseContext.cs index 59599eb64..9b4bdf6ca 100644 --- a/SharedLibraryCore/Database/DatabaseContext.cs +++ b/SharedLibraryCore/Database/DatabaseContext.cs @@ -16,6 +16,7 @@ namespace SharedLibraryCore.Database public DbSet Aliases { get; set; } public DbSet AliasLinks { get; set; } public DbSet Penalties { get; set; } + public DbSet EFMeta { get; set; } private static string _ConnectionString; diff --git a/SharedLibraryCore/Database/Models/EFClient.cs b/SharedLibraryCore/Database/Models/EFClient.cs index 249ed1f80..effea50a6 100644 --- a/SharedLibraryCore/Database/Models/EFClient.cs +++ b/SharedLibraryCore/Database/Models/EFClient.cs @@ -34,6 +34,8 @@ namespace SharedLibraryCore.Database.Models public string Password { get; set; } public string PasswordSalt { get; set; } + // list of meta for the client + public virtual ICollection Meta { get; set; } [NotMapped] public virtual string Name diff --git a/SharedLibraryCore/Database/Models/EFMeta.cs b/SharedLibraryCore/Database/Models/EFMeta.cs new file mode 100644 index 000000000..ac2eb4c30 --- /dev/null +++ b/SharedLibraryCore/Database/Models/EFMeta.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Text; + +namespace SharedLibraryCore.Database.Models +{ + /// + /// This class encapsulates any meta fields as a simple string + /// + public class EFMeta : SharedEntity + { + [Key] + public int MetaId { get; set; } + [Required] + public DateTime Created { get; set; } = DateTime.UtcNow; + [Required] + public DateTime Updated { get; set; } = DateTime.UtcNow; + [Required] + public int ClientId { get; set; } + [ForeignKey("ClientId")] // this is the client that the meta belongs to + public virtual EFClient Client { get; set; } + [Required] + [MinLength(3)] + public string Key { get; set; } + [Required] + public string Value { get; set; } + public string Extra { get; set; } + } +} diff --git a/SharedLibraryCore/Dtos/SharedInfo.cs b/SharedLibraryCore/Dtos/SharedInfo.cs index 018ab38a0..482a46a2a 100644 --- a/SharedLibraryCore/Dtos/SharedInfo.cs +++ b/SharedLibraryCore/Dtos/SharedInfo.cs @@ -4,5 +4,6 @@ namespace SharedLibraryCore.Dtos public class SharedInfo { public bool Sensitive { get; set; } + public bool Show { get; set; } = true; } } \ No newline at end of file diff --git a/SharedLibraryCore/Migrations/20180602041758_AddClientMeta.Designer.cs b/SharedLibraryCore/Migrations/20180602041758_AddClientMeta.Designer.cs new file mode 100644 index 000000000..037812aa1 --- /dev/null +++ b/SharedLibraryCore/Migrations/20180602041758_AddClientMeta.Designer.cs @@ -0,0 +1,540 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using SharedLibraryCore.Database; +using SharedLibraryCore.Objects; +using System; + +namespace SharedLibraryCore.Migrations +{ + [DbContext(typeof(DatabaseContext))] + [Migration("20180602041758_AddClientMeta")] + partial class AddClientMeta + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + 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("HitLoc"); + + b.Property("KillOriginVector3Id"); + + b.Property("Map"); + + b.Property("ServerId"); + + b.Property("VictimId"); + + b.Property("ViewAnglesVector3Id"); + + 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.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.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.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFRating"); + }); + + modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b => + { + b.Property("ServerId"); + + b.Property("Active"); + + 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(); + + b.HasKey("AliasId"); + + b.HasIndex("LinkId"); + + 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.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.ToTable("EFMeta"); + }); + + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd(); + + b.Property("Active"); + + b.Property("AutomatedOffense"); + + b.Property("Expires"); + + 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("X"); + + b.Property("Y"); + + b.Property("Z"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3"); + }); + + 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); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SharedLibraryCore/Migrations/20180602041758_AddClientMeta.cs b/SharedLibraryCore/Migrations/20180602041758_AddClientMeta.cs new file mode 100644 index 000000000..16a31f69e --- /dev/null +++ b/SharedLibraryCore/Migrations/20180602041758_AddClientMeta.cs @@ -0,0 +1,48 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Migrations +{ + public partial class AddClientMeta : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "EFMeta", + columns: table => new + { + MetaId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Active = table.Column(nullable: false), + ClientId = table.Column(nullable: false), + Created = table.Column(nullable: false), + Extra = table.Column(nullable: true), + Key = table.Column(nullable: false), + Updated = table.Column(nullable: false), + Value = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFMeta", x => x.MetaId); + table.ForeignKey( + name: "FK_EFMeta_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_EFMeta_ClientId", + table: "EFMeta", + column: "ClientId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "EFMeta"); + } + } +} diff --git a/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs b/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs index 065d690cb..8b4822e25 100644 --- a/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs +++ b/SharedLibraryCore/Migrations/DatabaseContextModelSnapshot.cs @@ -306,6 +306,34 @@ namespace SharedLibraryCore.Migrations 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.ToTable("EFMeta"); + }); + modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b => { b.Property("PenaltyId") @@ -480,6 +508,14 @@ namespace SharedLibraryCore.Migrations .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") diff --git a/SharedLibraryCore/Services/ClientService.cs b/SharedLibraryCore/Services/ClientService.cs index f6fd40988..87891a104 100644 --- a/SharedLibraryCore/Services/ClientService.cs +++ b/SharedLibraryCore/Services/ClientService.cs @@ -113,6 +113,7 @@ namespace SharedLibraryCore.Services var iqClient = from client in context.Clients .Include(c => c.CurrentAlias) .Include(c => c.AliasLink.Children) + .Include(c => c.Meta) where client.ClientId == entityID select new { diff --git a/WebfrontCore/Controllers/ClientController.cs b/WebfrontCore/Controllers/ClientController.cs index a61cbbff9..c15576727 100644 --- a/WebfrontCore/Controllers/ClientController.cs +++ b/WebfrontCore/Controllers/ClientController.cs @@ -81,6 +81,13 @@ namespace WebfrontCore.Controllers clientDto.Meta.AddRange(Authorized ? meta : meta.Where(m => !m.Sensitive)); clientDto.Meta.AddRange(Authorized ? penaltyMeta : penaltyMeta.Where(m => !m.Sensitive)); clientDto.Meta.AddRange(Authorized ? administeredPenaltiesMeta : administeredPenaltiesMeta.Where(m => !m.Sensitive)); + clientDto.Meta.AddRange(client.Meta.Select(m => new ProfileMeta() + { + When = m.Created, + Key = m.Key, + Value = m.Value, + Show = false, + })); clientDto.Meta = clientDto.Meta .OrderByDescending(m => m.When) .ToList(); diff --git a/WebfrontCore/Views/Client/Profile/Index.cshtml b/WebfrontCore/Views/Client/Profile/Index.cshtml index 796d06aac..cf4b3726f 100644 --- a/WebfrontCore/Views/Client/Profile/Index.cshtml +++ b/WebfrontCore/Views/Client/Profile/Index.cshtml @@ -3,11 +3,15 @@ string match = System.Text.RegularExpressions.Regex.Match(Model.Name.ToUpper(), "[A-Z]").Value; string shortCode = match == string.Empty ? "?" : match; var loc = SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex; + string gravatarUrl = Model.Meta.FirstOrDefault(m => m.Key == "GravatarEmail")?.Value; }
-
- @shortCode +
+ @if (string.IsNullOrEmpty(gravatarUrl)) + { + @shortCode + }
@@ -31,7 +35,7 @@
@if (Model.LevelInt < (int)ViewBag.User.Level && - (SharedLibraryCore.Objects.Player.Permission)Model.LevelInt != SharedLibraryCore.Objects.Player.Permission.Banned) +(SharedLibraryCore.Objects.Player.Permission)Model.LevelInt != SharedLibraryCore.Objects.Player.Permission.Banned) { } @@ -47,7 +51,7 @@ @{ foreach (var linked in Model.LinkedAccounts) { - @Html.ActionLink(linked.Value.ToString("X"), "ProfileAsync", "Client", new { id = linked.Key}, new { @class = "link-inverse" })
+ @Html.ActionLink(linked.Value.ToString("X"), "ProfileAsync", "Client", new { id = linked.Key }, new { @class = "link-inverse" })
} foreach (string alias in Model.Aliases) { @@ -100,7 +104,7 @@ diff --git a/version.txt b/version.txt index 298984d43..3a97680cf 100644 --- a/version.txt +++ b/version.txt @@ -1,3 +1,6 @@ +Version 2.2: +-added top player stats page + Version 2.1: CHANGELOG: -add support for localization (Russian, Spanish, and Portuguese)