diff --git a/ProjectLighthouse/Controllers/PhotosController.cs b/ProjectLighthouse/Controllers/PhotosController.cs index 6d30d184..8f8414a7 100644 --- a/ProjectLighthouse/Controllers/PhotosController.cs +++ b/ProjectLighthouse/Controllers/PhotosController.cs @@ -9,6 +9,7 @@ using Kettu; using LBPUnion.ProjectLighthouse.Logging; using LBPUnion.ProjectLighthouse.Serialization; using LBPUnion.ProjectLighthouse.Types; +using LBPUnion.ProjectLighthouse.Types.Settings; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; @@ -32,6 +33,8 @@ namespace LBPUnion.ProjectLighthouse.Controllers User? user = await this.database.UserFromGameRequest(this.Request); if (user == null) return this.StatusCode(403, ""); + if (user.PhotosByMe >= ServerSettings.Instance.PhotosQuota) return this.BadRequest(); + this.Request.Body.Position = 0; string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync(); @@ -39,6 +42,14 @@ namespace LBPUnion.ProjectLighthouse.Controllers Photo? photo = (Photo?)serializer.Deserialize(new StringReader(bodyString)); if (photo == null) return this.BadRequest(); + foreach (Photo p in this.database.Photos.Where(p => p.CreatorId == user.UserId)) + { + if (p.LargeHash == photo.LargeHash) return this.Ok(); // photo already uplaoded + if (p.MediumHash == photo.MediumHash) return this.Ok(); + if (p.SmallHash == photo.SmallHash) return this.Ok(); + if (p.PlanHash == photo.PlanHash) return this.Ok(); + } + photo.CreatorId = user.UserId; photo.Creator = user; diff --git a/ProjectLighthouse/Controllers/PublishController.cs b/ProjectLighthouse/Controllers/PublishController.cs index 98f490e2..ecf7a66d 100644 --- a/ProjectLighthouse/Controllers/PublishController.cs +++ b/ProjectLighthouse/Controllers/PublishController.cs @@ -9,6 +9,7 @@ using LBPUnion.ProjectLighthouse.Serialization; using LBPUnion.ProjectLighthouse.Types; using LBPUnion.ProjectLighthouse.Types.Levels; using LBPUnion.ProjectLighthouse.Types.Profiles; +using LBPUnion.ProjectLighthouse.Types.Settings; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; @@ -35,6 +36,8 @@ namespace LBPUnion.ProjectLighthouse.Controllers User? user = await this.database.UserFromGameRequest(this.Request); if (user == null) return this.StatusCode(403, ""); + if (user.UsedSlots >= ServerSettings.Instance.EntitledSlots) return this.BadRequest(); + Slot? slot = await this.GetSlotFromBody(); if (slot == null) return this.BadRequest(); // if the level cant be parsed then it obviously cant be uploaded @@ -74,6 +77,8 @@ namespace LBPUnion.ProjectLighthouse.Controllers User user = userAndToken.Value.Item1; GameToken gameToken = userAndToken.Value.Item2; + if (user.UsedSlots >= ServerSettings.Instance.EntitledSlots) return this.BadRequest(); + Slot? slot = await this.GetSlotFromBody(); if (slot?.Location == null) return this.BadRequest(); diff --git a/ProjectLighthouse/Database.cs b/ProjectLighthouse/Database.cs index 6e84e6ef..2af08e30 100644 --- a/ProjectLighthouse/Database.cs +++ b/ProjectLighthouse/Database.cs @@ -6,8 +6,8 @@ using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Logging; using LBPUnion.ProjectLighthouse.Types; using LBPUnion.ProjectLighthouse.Types.Levels; -using LBPUnion.ProjectLighthouse.Types.Reviews; using LBPUnion.ProjectLighthouse.Types.Profiles; +using LBPUnion.ProjectLighthouse.Types.Reviews; using LBPUnion.ProjectLighthouse.Types.Settings; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; @@ -63,7 +63,7 @@ namespace LBPUnion.ProjectLighthouse return user; } -#nullable enable + #nullable enable public async Task AuthenticateUser(LoginData loginData, string userLocation, string titleId = "") { // TODO: don't use psn name to authenticate @@ -255,6 +255,37 @@ namespace LBPUnion.ProjectLighthouse public async Task PhotoFromSubject(PhotoSubject subject) => await this.Photos.FirstOrDefaultAsync(p => p.PhotoSubjectIds.Contains(subject.PhotoSubjectId.ToString())); -#nullable disable + + public async Task RemoveUser(User user) + { + this.Locations.Remove(user.Location); + LastContact? lastContact = await this.LastContacts.FirstOrDefaultAsync(l => l.UserId == user.UserId); + if (lastContact != null) this.LastContacts.Remove(lastContact); + + foreach (Slot slot in this.Slots.Where(s => s.CreatorId == user.UserId)) await this.RemoveSlot(slot, false); + + this.AuthenticationAttempts.RemoveRange(this.AuthenticationAttempts.Include(a => a.GameToken).Where(a => a.GameToken.UserId == user.UserId)); + this.HeartedProfiles.RemoveRange(this.HeartedProfiles.Where(h => h.UserId == user.UserId)); + this.PhotoSubjects.RemoveRange(this.PhotoSubjects.Where(s => s.UserId == user.UserId)); + this.HeartedLevels.RemoveRange(this.HeartedLevels.Where(h => h.UserId == user.UserId)); + this.VisitedLevels.RemoveRange(this.VisitedLevels.Where(v => v.UserId == user.UserId)); + this.QueuedLevels.RemoveRange(this.QueuedLevels.Where(q => q.UserId == user.UserId)); + this.RatedLevels.RemoveRange(this.RatedLevels.Where(r => r.UserId == user.UserId)); + this.GameTokens.RemoveRange(this.GameTokens.Where(t => t.UserId == user.UserId)); + this.WebTokens.RemoveRange(this.WebTokens.Where(t => t.UserId == user.UserId)); + this.Comments.RemoveRange(this.Comments.Where(c => c.PosterUserId == user.UserId)); + this.Photos.RemoveRange(this.Photos.Where(p => p.CreatorId == user.UserId)); + + await this.SaveChangesAsync(); + } + + public async Task RemoveSlot(Slot slot, bool saveChanges = true) + { + if (slot.Location != null) this.Locations.Remove(slot.Location); + this.Slots.Remove(slot); + + if (saveChanges) await this.SaveChangesAsync(); + } + #nullable disable } } \ No newline at end of file diff --git a/ProjectLighthouse/Maintenance/Commands/DeleteUserCommand.cs b/ProjectLighthouse/Maintenance/Commands/DeleteUserCommand.cs new file mode 100644 index 00000000..a0e0f8d1 --- /dev/null +++ b/ProjectLighthouse/Maintenance/Commands/DeleteUserCommand.cs @@ -0,0 +1,42 @@ +#nullable enable +using System; +using System.Threading.Tasks; +using JetBrains.Annotations; +using LBPUnion.ProjectLighthouse.Types; +using Microsoft.EntityFrameworkCore; + +namespace LBPUnion.ProjectLighthouse.Maintenance.Commands +{ + [UsedImplicitly] + public class DeleteUserCommand : ICommand + { + private readonly Database database = new(); + public string Name() => "Delete/Ban User"; + public string[] Aliases() + => new[] + { + "deleteUser", "wipeUser", "banUser", + }; + public string Arguments() => ""; + public int RequiredArgs() => 1; + public async Task Run(string[] args) + { + User? user = await this.database.Users.FirstOrDefaultAsync(u => u.Username == args[0]); + if (user == null) + { + try + { + user = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == Convert.ToInt32(args[0])); + if (user == null) throw new Exception(); + } + catch + { + Console.WriteLine($"Could not find user by parameter '{args[0]}'"); + return; + } + } + + await this.database.RemoveUser(user); + } + } +} \ No newline at end of file diff --git a/ProjectLighthouse/Types/Settings/ServerSettings.cs b/ProjectLighthouse/Types/Settings/ServerSettings.cs index e4caf307..820c1a18 100644 --- a/ProjectLighthouse/Types/Settings/ServerSettings.cs +++ b/ProjectLighthouse/Types/Settings/ServerSettings.cs @@ -63,7 +63,7 @@ namespace LBPUnion.ProjectLighthouse.Types.Settings } } - public const int CurrentConfigVersion = 11; // MUST BE INCREMENTED FOR EVERY CONFIG CHANGE! + public const int CurrentConfigVersion = 12; // MUST BE INCREMENTED FOR EVERY CONFIG CHANGE! #region Meta @@ -103,6 +103,8 @@ namespace LBPUnion.ProjectLighthouse.Types.Settings public int ListsQuota { get; set; } = 50; + public int PhotosQuota { get; set; } = 500; + public bool GoogleAnalyticsEnabled { get; set; } = false; public string GoogleAnalyticsId { get; set; } = "";