mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-05-14 22:02:26 +00:00
Fix bug where users can't be deleted (#648)
* Add username to mod cases if user is deleted * Add timezone package to docker container * Remove extra space in migration sql statement * Changes from self-review
This commit is contained in:
parent
2c2f31ad38
commit
4559d26a54
15 changed files with 170 additions and 83 deletions
|
@ -3,7 +3,7 @@
|
||||||
"isRoot": true,
|
"isRoot": true,
|
||||||
"tools": {
|
"tools": {
|
||||||
"dotnet-ef": {
|
"dotnet-ef": {
|
||||||
"version": "7.0.1",
|
"version": "7.0.2",
|
||||||
"commands": [
|
"commands": [
|
||||||
"dotnet-ef"
|
"dotnet-ef"
|
||||||
]
|
]
|
||||||
|
|
|
@ -24,7 +24,7 @@ adduser -S lighthouse -G lighthouse -h /lighthouse --uid 1001 && \
|
||||||
mkdir -p /lighthouse/data && \
|
mkdir -p /lighthouse/data && \
|
||||||
mkdir -p /lighthouse/app && \
|
mkdir -p /lighthouse/app && \
|
||||||
mkdir -p /lighthouse/temp && \
|
mkdir -p /lighthouse/temp && \
|
||||||
apk add --no-cache icu-libs su-exec
|
apk add --no-cache icu-libs su-exec tzdata
|
||||||
|
|
||||||
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
|
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ public class ModerationCaseController : ControllerBase
|
||||||
|
|
||||||
@case.DismissedAt = DateTime.Now;
|
@case.DismissedAt = DateTime.Now;
|
||||||
@case.DismisserId = user.UserId;
|
@case.DismisserId = user.UserId;
|
||||||
|
@case.DismisserUsername = user.Username;
|
||||||
|
|
||||||
@case.Processed = false;
|
@case.Processed = false;
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,8 @@ public class NewCasePage : BaseLayout
|
||||||
if (type == null) return this.BadRequest();
|
if (type == null) return this.BadRequest();
|
||||||
if (affectedId == null) return this.BadRequest();
|
if (affectedId == null) return this.BadRequest();
|
||||||
|
|
||||||
this.Type = (CaseType)type;
|
this.Type = type.Value;
|
||||||
this.AffectedId = (int)affectedId;
|
this.AffectedId = affectedId.Value;
|
||||||
|
|
||||||
return this.Page();
|
return this.Page();
|
||||||
}
|
}
|
||||||
|
@ -38,19 +38,19 @@ public class NewCasePage : BaseLayout
|
||||||
reason ??= string.Empty;
|
reason ??= string.Empty;
|
||||||
modNotes ??= string.Empty;
|
modNotes ??= string.Empty;
|
||||||
|
|
||||||
// this is fucking ugly
|
|
||||||
// if id is invalid then return bad request
|
// if id is invalid then return bad request
|
||||||
if (!(await ((CaseType)type).IsIdValid((int)affectedId, this.Database))) return this.BadRequest();
|
if (!await type.Value.IsIdValid((int)affectedId, this.Database)) return this.BadRequest();
|
||||||
|
|
||||||
ModerationCase @case = new()
|
ModerationCase @case = new()
|
||||||
{
|
{
|
||||||
Type = (CaseType)type,
|
Type = type.Value,
|
||||||
Reason = reason,
|
Reason = reason,
|
||||||
ModeratorNotes = modNotes,
|
ModeratorNotes = modNotes,
|
||||||
ExpiresAt = expires,
|
ExpiresAt = expires,
|
||||||
CreatedAt = DateTime.Now,
|
CreatedAt = DateTime.Now,
|
||||||
CreatorId = user.UserId,
|
CreatorId = user.UserId,
|
||||||
AffectedId = (int)affectedId,
|
CreatorUsername = user.Username,
|
||||||
|
AffectedId = affectedId.Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Database.Cases.Add(@case);
|
this.Database.Cases.Add(@case);
|
||||||
|
|
|
@ -21,24 +21,44 @@
|
||||||
|
|
||||||
@if (Model.Dismissed)
|
@if (Model.Dismissed)
|
||||||
{
|
{
|
||||||
Debug.Assert(Model.Dismisser != null);
|
|
||||||
Debug.Assert(Model.DismissedAt != null);
|
Debug.Assert(Model.DismissedAt != null);
|
||||||
|
|
||||||
<h3 class="ui @color header">
|
@if (Model.Dismisser != null)
|
||||||
This case was dismissed by <a href="/user/@Model.Dismisser.UserId">@Model.Dismisser.Username</a> on @TimeZoneInfo.ConvertTime(Model.DismissedAt.Value, timeZoneInfo).ToString("M/d/yyyy @ h:mm tt").
|
|
||||||
</h3>
|
|
||||||
}
|
|
||||||
else if (Model.Expired && Model.ExpiresAt != null)
|
|
||||||
{
|
{
|
||||||
<h3 class="ui @color header">
|
<h3 class="ui @color header">
|
||||||
This case expired on @TimeZoneInfo.ConvertTime(Model.ExpiresAt.Value, timeZoneInfo).ToString("M/d/yyyy @ h:mm tt").
|
This case was dismissed by <a href="/user/@Model.Dismisser.UserId">@Model.DismisserUsername</a> on @TimeZoneInfo.ConvertTime(Model.DismissedAt.Value, timeZoneInfo).ToString("M/d/yyyy @ h:mm tt").
|
||||||
|
</h3>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<h3 class="ui @color header">
|
||||||
|
This case was dismissed by @Model.DismisserUsername on @TimeZoneInfo.ConvertTime(Model.DismissedAt.Value, timeZoneInfo).ToString("M/d/yyyy @ h:mm tt").
|
||||||
</h3>
|
</h3>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (Model.Expired)
|
||||||
|
{
|
||||||
|
<h3 class="ui @color header">
|
||||||
|
This case expired on @TimeZoneInfo.ConvertTime(Model.ExpiresAt!.Value, timeZoneInfo).ToString("M/d/yyyy @ h:mm tt").
|
||||||
|
</h3>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (Model.Creator != null && Model.Creator.Username.Length != 0)
|
||||||
|
{
|
||||||
<span>
|
<span>
|
||||||
Case created by <a href="/user/@Model.Creator!.UserId">@Model.Creator.Username</a>
|
Case created by <a href="/user/@Model.Creator.UserId">@Model.Creator.Username</a>
|
||||||
on @TimeZoneInfo.ConvertTime(Model.CreatedAt, timeZoneInfo).ToString("M/d/yyyy @ h:mm tt")
|
on @TimeZoneInfo.ConvertTime(Model.CreatedAt, timeZoneInfo).ToString("M/d/yyyy @ h:mm tt")
|
||||||
</span><br>
|
</span><br>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span>
|
||||||
|
Case created by @Model.CreatorUsername
|
||||||
|
on @TimeZoneInfo.ConvertTime(Model.CreatedAt, timeZoneInfo).ToString("M/d/yyyy @ h:mm tt")
|
||||||
|
</span><br>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@if (Model.Type.AffectsLevel())
|
@if (Model.Type.AffectsLevel())
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,6 +48,6 @@ public static class CaseTypeExtensions
|
||||||
if (type.AffectsUser()) return await database.Users.Has(u => u.UserId == affectedId);
|
if (type.AffectsUser()) return await database.Users.Has(u => u.UserId == affectedId);
|
||||||
if (type.AffectsLevel()) return await database.Slots.Has(u => u.SlotId == affectedId);
|
if (type.AffectsLevel()) return await database.Slots.Has(u => u.SlotId == affectedId);
|
||||||
|
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException(nameof(type));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -30,14 +30,18 @@ public class ModerationCase
|
||||||
|
|
||||||
public DateTime? DismissedAt { get; set; }
|
public DateTime? DismissedAt { get; set; }
|
||||||
public bool Dismissed => this.DismissedAt != null;
|
public bool Dismissed => this.DismissedAt != null;
|
||||||
|
|
||||||
public int? DismisserId { get; set; }
|
public int? DismisserId { get; set; }
|
||||||
|
public string? DismisserUsername { get; set; }
|
||||||
|
|
||||||
[ForeignKey(nameof(DismisserId))]
|
[ForeignKey(nameof(DismisserId))]
|
||||||
public User? Dismisser { get; set; }
|
public virtual User? Dismisser { get; set; }
|
||||||
|
|
||||||
public int CreatorId { get; set; }
|
public int CreatorId { get; set; }
|
||||||
|
public required string CreatorUsername { get; set; }
|
||||||
|
|
||||||
[ForeignKey(nameof(CreatorId))]
|
[ForeignKey(nameof(CreatorId))]
|
||||||
public User? Creator { get; set; }
|
public virtual User? Creator { get; set; }
|
||||||
|
|
||||||
public int AffectedId { get; set; }
|
public int AffectedId { get; set; }
|
||||||
|
|
||||||
|
@ -54,24 +58,4 @@ public class ModerationCase
|
||||||
return database.Slots.FirstOrDefaultAsync(u => u.SlotId == this.AffectedId);
|
return database.Slots.FirstOrDefaultAsync(u => u.SlotId == this.AffectedId);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Case creators
|
|
||||||
#region Level
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region User
|
|
||||||
public static ModerationCase NewBanCase(int caseCreator, int userId, string reason, string modNotes, DateTime caseExpires)
|
|
||||||
=> new()
|
|
||||||
{
|
|
||||||
Type = CaseType.UserBan,
|
|
||||||
Reason = $"Banned for reason '{reason}'\nModeration notes: {modNotes}",
|
|
||||||
CreatorId = caseCreator,
|
|
||||||
CreatedAt = DateTime.Now,
|
|
||||||
ExpiresAt = caseExpires,
|
|
||||||
AffectedId = userId,
|
|
||||||
};
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
|
@ -517,6 +517,16 @@ public class Database : DbContext
|
||||||
LastContact? lastContact = await this.LastContacts.FirstOrDefaultAsync(l => l.UserId == user.UserId);
|
LastContact? lastContact = await this.LastContacts.FirstOrDefaultAsync(l => l.UserId == user.UserId);
|
||||||
if (lastContact != null) this.LastContacts.Remove(lastContact);
|
if (lastContact != null) this.LastContacts.Remove(lastContact);
|
||||||
|
|
||||||
|
foreach (ModerationCase modCase in await this.Cases
|
||||||
|
.Where(c => c.CreatorId == user.UserId || c.DismisserId == user.UserId)
|
||||||
|
.ToListAsync())
|
||||||
|
{
|
||||||
|
if(modCase.DismisserId == user.UserId)
|
||||||
|
modCase.DismisserId = null;
|
||||||
|
if(modCase.CreatorId == user.UserId)
|
||||||
|
modCase.CreatorId = await SlotHelper.GetPlaceholderUserId(this);
|
||||||
|
}
|
||||||
|
|
||||||
foreach (Slot slot in this.Slots.Where(s => s.CreatorId == user.UserId)) await this.RemoveSlot(slot, false);
|
foreach (Slot slot in this.Slots.Where(s => s.CreatorId == user.UserId)) await this.RemoveSlot(slot, false);
|
||||||
|
|
||||||
this.HeartedProfiles.RemoveRange(this.HeartedProfiles.Where(h => h.UserId == user.UserId));
|
this.HeartedProfiles.RemoveRange(this.HeartedProfiles.Where(h => h.UserId == user.UserId));
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
namespace LBPUnion.ProjectLighthouse.Helpers;
|
|
||||||
|
|
||||||
public static class LocalizationHelper
|
|
||||||
{}
|
|
|
@ -41,6 +41,56 @@ public static class SlotHelper
|
||||||
|
|
||||||
private static readonly SemaphoreSlim semaphore = new(1, 1);
|
private static readonly SemaphoreSlim semaphore = new(1, 1);
|
||||||
|
|
||||||
|
private static async Task<int> GetPlaceholderLocationId(Database database)
|
||||||
|
{
|
||||||
|
Location? devLocation = await database.Locations.FirstOrDefaultAsync(l => l.Id == 1);
|
||||||
|
|
||||||
|
if (devLocation != null) return devLocation.Id;
|
||||||
|
|
||||||
|
await semaphore.WaitAsync(TimeSpan.FromSeconds(5));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
devLocation = new Location
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
};
|
||||||
|
database.Locations.Add(devLocation);
|
||||||
|
return devLocation.Id;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
semaphore.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<int> GetPlaceholderUserId(Database database)
|
||||||
|
{
|
||||||
|
int devCreatorId = await database.Users.Where(u => u.Username.Length == 0)
|
||||||
|
.Select(u => u.UserId)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
if (devCreatorId != 0) return devCreatorId;
|
||||||
|
|
||||||
|
await semaphore.WaitAsync(TimeSpan.FromSeconds(5));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
User devCreator = new()
|
||||||
|
{
|
||||||
|
Username = "",
|
||||||
|
PermissionLevel = PermissionLevel.Banned,
|
||||||
|
Biography = "Placeholder author of story levels",
|
||||||
|
BannedReason = "Banned to not show in users list",
|
||||||
|
LocationId = await GetPlaceholderLocationId(database),
|
||||||
|
};
|
||||||
|
database.Users.Add(devCreator);
|
||||||
|
await database.SaveChangesAsync();
|
||||||
|
return devCreator.UserId;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
semaphore.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task<int> GetPlaceholderSlotId(Database database, int guid, SlotType slotType)
|
public static async Task<int> GetPlaceholderSlotId(Database database, int guid, SlotType slotType)
|
||||||
{
|
{
|
||||||
int slotId = await database.Slots.Where(s => s.Type == slotType && s.InternalSlotId == guid).Select(s => s.SlotId).FirstOrDefaultAsync();
|
int slotId = await database.Slots.Where(s => s.Type == slotType && s.InternalSlotId == guid).Select(s => s.SlotId).FirstOrDefaultAsync();
|
||||||
|
@ -58,31 +108,7 @@ public static class SlotHelper
|
||||||
|
|
||||||
if (slotId != 0) return slotId;
|
if (slotId != 0) return slotId;
|
||||||
|
|
||||||
Location? devLocation = await database.Locations.FirstOrDefaultAsync(l => l.Id == 1);
|
int devCreatorId = await GetPlaceholderUserId(database);
|
||||||
if (devLocation == null)
|
|
||||||
{
|
|
||||||
devLocation = new Location
|
|
||||||
{
|
|
||||||
Id = 1,
|
|
||||||
};
|
|
||||||
database.Locations.Add(devLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
int devCreatorId = await database.Users.Where(u => u.Username.Length == 0).Select(u => u.UserId).FirstOrDefaultAsync();
|
|
||||||
if (devCreatorId == 0)
|
|
||||||
{
|
|
||||||
User devCreator = new()
|
|
||||||
{
|
|
||||||
Username = "",
|
|
||||||
PermissionLevel = PermissionLevel.Banned,
|
|
||||||
Biography = "Placeholder author of story levels",
|
|
||||||
BannedReason = "Banned to not show in users list",
|
|
||||||
LocationId = devLocation.Id,
|
|
||||||
};
|
|
||||||
database.Users.Add(devCreator);
|
|
||||||
await database.SaveChangesAsync();
|
|
||||||
devCreatorId = devCreator.UserId;
|
|
||||||
}
|
|
||||||
|
|
||||||
Slot slot = new()
|
Slot slot = new()
|
||||||
{
|
{
|
||||||
|
@ -90,7 +116,7 @@ public static class SlotHelper
|
||||||
Description = $"Placeholder for {slotType} type level",
|
Description = $"Placeholder for {slotType} type level",
|
||||||
CreatorId = devCreatorId,
|
CreatorId = devCreatorId,
|
||||||
InternalSlotId = guid,
|
InternalSlotId = guid,
|
||||||
LocationId = devLocation.Id,
|
LocationId = await GetPlaceholderLocationId(database),
|
||||||
Type = slotType,
|
Type = slotType,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -103,5 +129,4 @@ public static class SlotHelper
|
||||||
semaphore.Release();
|
semaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -4,13 +4,13 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using LBPUnion.ProjectLighthouse.Extensions;
|
using LBPUnion.ProjectLighthouse.Extensions;
|
||||||
using LBPUnion.ProjectLighthouse.PlayerData;
|
using LBPUnion.ProjectLighthouse.PlayerData;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using YamlDotNet.Core.Tokens;
|
using YamlDotNet.Core.Tokens;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Levels.Categories;
|
namespace LBPUnion.ProjectLighthouse.Levels.Categories;
|
||||||
|
|
||||||
public class HighestRatedCategory : Category
|
public class HighestRatedCategory : Category
|
||||||
{
|
{
|
||||||
Random rand = new();
|
|
||||||
public override string Name { get; set; } = "Highest Rated";
|
public override string Name { get; set; } = "Highest Rated";
|
||||||
public override string Description { get; set; } = "Community Highest Rated content";
|
public override string Description { get; set; } = "Community Highest Rated content";
|
||||||
public override string IconHash { get; set; } = "g820603";
|
public override string IconHash { get; set; } = "g820603";
|
||||||
|
@ -21,7 +21,7 @@ public class HighestRatedCategory : Category
|
||||||
=> database.Slots.ByGameVersion(GameVersion.LittleBigPlanet3, false, true)
|
=> database.Slots.ByGameVersion(GameVersion.LittleBigPlanet3, false, true)
|
||||||
.AsEnumerable()
|
.AsEnumerable()
|
||||||
.OrderByDescending(s => s.Thumbsup)
|
.OrderByDescending(s => s.Thumbsup)
|
||||||
.ThenBy(_ => rand.Next())
|
.ThenBy(_ => EF.Functions.Random())
|
||||||
.Skip(Math.Max(0, pageStart - 1))
|
.Skip(Math.Max(0, pageStart - 1))
|
||||||
.Take(Math.Min(pageSize, 20));
|
.Take(Math.Min(pageSize, 20));
|
||||||
public override int GetTotalSlots(Database database) => database.Slots.Count(s => s.Type == SlotType.User);
|
public override int GetTotalSlots(Database database) => database.Slots.Count(s => s.Type == SlotType.User);
|
||||||
|
|
|
@ -4,23 +4,23 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using LBPUnion.ProjectLighthouse.Extensions;
|
using LBPUnion.ProjectLighthouse.Extensions;
|
||||||
using LBPUnion.ProjectLighthouse.PlayerData;
|
using LBPUnion.ProjectLighthouse.PlayerData;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Levels.Categories;
|
namespace LBPUnion.ProjectLighthouse.Levels.Categories;
|
||||||
|
|
||||||
public class MostHeartedCategory : Category
|
public class MostHeartedCategory : Category
|
||||||
{
|
{
|
||||||
Random rand = new();
|
|
||||||
public override string Name { get; set; } = "Most Hearted";
|
public override string Name { get; set; } = "Most Hearted";
|
||||||
public override string Description { get; set; } = "The Most Hearted Content";
|
public override string Description { get; set; } = "The Most Hearted Content";
|
||||||
public override string IconHash { get; set; } = "g820607";
|
public override string IconHash { get; set; } = "g820607";
|
||||||
public override string Endpoint { get; set; } = "mostHearted";
|
public override string Endpoint { get; set; } = "mostHearted";
|
||||||
public override Slot? GetPreviewSlot(Database database) => database.Slots.Where(s => s.Type == SlotType.User).AsEnumerable().OrderByDescending(s => s.Hearts).FirstOrDefault();
|
public override Slot? GetPreviewSlot(Database database) => database.Slots.Where(s => s.Type == SlotType.User).AsEnumerable().MaxBy(s => s.Hearts);
|
||||||
public override IEnumerable<Slot> GetSlots
|
public override IEnumerable<Slot> GetSlots
|
||||||
(Database database, int pageStart, int pageSize)
|
(Database database, int pageStart, int pageSize)
|
||||||
=> database.Slots.ByGameVersion(GameVersion.LittleBigPlanet3, false, true)
|
=> database.Slots.ByGameVersion(GameVersion.LittleBigPlanet3, false, true)
|
||||||
.AsEnumerable()
|
.AsEnumerable()
|
||||||
.OrderByDescending(s => s.Hearts)
|
.OrderByDescending(s => s.Hearts)
|
||||||
.ThenBy(_ => rand.Next())
|
.ThenBy(_ => EF.Functions.Random())
|
||||||
.Skip(Math.Max(0, pageStart - 1))
|
.Skip(Math.Max(0, pageStart - 1))
|
||||||
.Take(Math.Min(pageSize, 20));
|
.Take(Math.Min(pageSize, 20));
|
||||||
public override int GetTotalSlots(Database database) => database.Slots.Count(s => s.Type == SlotType.User);
|
public override int GetTotalSlots(Database database) => database.Slots.Count(s => s.Type == SlotType.User);
|
||||||
|
|
|
@ -4,24 +4,23 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using LBPUnion.ProjectLighthouse.Extensions;
|
using LBPUnion.ProjectLighthouse.Extensions;
|
||||||
using LBPUnion.ProjectLighthouse.PlayerData;
|
using LBPUnion.ProjectLighthouse.PlayerData;
|
||||||
using YamlDotNet.Core.Tokens;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Levels.Categories;
|
namespace LBPUnion.ProjectLighthouse.Levels.Categories;
|
||||||
|
|
||||||
public class MostPlayedCategory : Category
|
public class MostPlayedCategory : Category
|
||||||
{
|
{
|
||||||
Random rand = new();
|
|
||||||
public override string Name { get; set; } = "Most Played";
|
public override string Name { get; set; } = "Most Played";
|
||||||
public override string Description { get; set; } = "The most played content";
|
public override string Description { get; set; } = "The most played content";
|
||||||
public override string IconHash { get; set; } = "g820608";
|
public override string IconHash { get; set; } = "g820608";
|
||||||
public override string Endpoint { get; set; } = "mostUniquePlays";
|
public override string Endpoint { get; set; } = "mostUniquePlays";
|
||||||
public override Slot? GetPreviewSlot(Database database) => database.Slots.Where(s => s.Type == SlotType.User).AsEnumerable().OrderByDescending(s => s.PlaysUnique).FirstOrDefault();
|
public override Slot? GetPreviewSlot(Database database) => database.Slots.Where(s => s.Type == SlotType.User).AsEnumerable().MaxBy(s => s.PlaysUnique);
|
||||||
public override IEnumerable<Slot> GetSlots
|
public override IEnumerable<Slot> GetSlots
|
||||||
(Database database, int pageStart, int pageSize)
|
(Database database, int pageStart, int pageSize)
|
||||||
=> database.Slots.ByGameVersion(GameVersion.LittleBigPlanet3, false, true)
|
=> database.Slots.ByGameVersion(GameVersion.LittleBigPlanet3, false, true)
|
||||||
.AsEnumerable()
|
.AsEnumerable()
|
||||||
.OrderByDescending(s => s.PlaysUnique)
|
.OrderByDescending(s => s.PlaysUnique)
|
||||||
.ThenBy(_ => rand.Next())
|
.ThenBy(_ => EF.Functions.Random())
|
||||||
.Skip(Math.Max(0, pageStart - 1))
|
.Skip(Math.Max(0, pageStart - 1))
|
||||||
.Take(Math.Min(pageSize, 20));
|
.Take(Math.Min(pageSize, 20));
|
||||||
public override int GetTotalSlots(Database database) => database.Slots.Count(s => s.Type == SlotType.User);
|
public override int GetTotalSlots(Database database) => database.Slots.Count(s => s.Type == SlotType.User);
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
using LBPUnion.ProjectLighthouse;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace ProjectLighthouse.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(Database))]
|
||||||
|
[Migration("20230127021453_AddUsernameToCaseTable")]
|
||||||
|
public partial class AddUsernameToCaseTable : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "CreatorUsername",
|
||||||
|
table: "Cases",
|
||||||
|
type: "longtext",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "")
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "DismisserUsername",
|
||||||
|
table: "Cases",
|
||||||
|
type: "longtext",
|
||||||
|
nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.Sql("UPDATE Cases INNER JOIN Users ON Cases.CreatorId = Users.UserId SET Cases.CreatorUsername = Users.Username WHERE Cases.CreatorUsername = '';");
|
||||||
|
migrationBuilder.Sql("UPDATE Cases INNER JOIN Users ON Cases.DismisserId = Users.UserId SET Cases.DismisserUsername = Users.Username WHERE Cases.DismisserUsername is NULL;");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "CreatorUsername",
|
||||||
|
table: "Cases");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "DismisserUsername",
|
||||||
|
table: "Cases");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ namespace ProjectLighthouse.Migrations
|
||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.HasAnnotation("ProductVersion", "7.0.1")
|
.HasAnnotation("ProductVersion", "7.0.2")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||||
|
|
||||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Administration.CompletedMigration", b =>
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Administration.CompletedMigration", b =>
|
||||||
|
@ -47,12 +47,19 @@ namespace ProjectLighthouse.Migrations
|
||||||
b.Property<int>("CreatorId")
|
b.Property<int>("CreatorId")
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("CreatorUsername")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
b.Property<DateTime?>("DismissedAt")
|
b.Property<DateTime?>("DismissedAt")
|
||||||
.HasColumnType("datetime(6)");
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
b.Property<int?>("DismisserId")
|
b.Property<int?>("DismisserId")
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("DismisserUsername")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
b.Property<DateTime?>("ExpiresAt")
|
b.Property<DateTime?>("ExpiresAt")
|
||||||
.HasColumnType("datetime(6)");
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue