mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-07-24 22:21:30 +00:00
Add proper relationships to Comments (#838)
* Add specific foreign keys for comment targets * Remove inheritdoc tags from migration * Fix punctuation of deleted comment message and add mod deletion message * Fix broken merge * Cleanup comment queries
This commit is contained in:
parent
9cb9fb62e4
commit
a316c866c5
13 changed files with 192 additions and 45 deletions
|
@ -64,12 +64,16 @@ public class CommentController : ControllerBase
|
|||
|
||||
PaginationData pageData = this.Request.GetPaginationData();
|
||||
|
||||
IQueryable<CommentEntity> baseQuery = this.database.Comments.Where(c => c.Type == type);
|
||||
|
||||
if (type == CommentType.Level)
|
||||
{
|
||||
targetId = await this.database.Slots.Where(s => s.SlotId == slotId)
|
||||
.Where(s => s.CommentsEnabled && !s.Hidden)
|
||||
.Select(s => s.SlotId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
baseQuery = baseQuery.Where(c => c.TargetSlotId == targetId);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -77,6 +81,8 @@ public class CommentController : ControllerBase
|
|||
.Where(u => u.CommentsEnabled)
|
||||
.Select(u => u.UserId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
baseQuery = baseQuery.Where(c => c.TargetUserId == targetId);
|
||||
}
|
||||
|
||||
if (targetId == 0) return this.NotFound();
|
||||
|
@ -86,11 +92,10 @@ public class CommentController : ControllerBase
|
|||
where blockedProfile.UserId == token.UserId
|
||||
select blockedProfile.BlockedUserId).ToListAsync();
|
||||
|
||||
List<GameComment> comments = (await this.database.Comments.Where(p => p.TargetId == targetId && p.Type == type)
|
||||
.OrderByDescending(p => p.Timestamp)
|
||||
.Where(p => !blockedUsers.Contains(p.PosterUserId))
|
||||
List<GameComment> comments = (await baseQuery.OrderByDescending(c => c.Timestamp)
|
||||
.Where(c => !blockedUsers.Contains(c.PosterUserId))
|
||||
.Include(c => c.Poster)
|
||||
.Where(p => p.Poster.PermissionLevel != PermissionLevel.Banned)
|
||||
.Where(c => c.Poster.PermissionLevel != PermissionLevel.Banned)
|
||||
.ApplyPagination(pageData)
|
||||
.ToListAsync()).ToSerializableList(c => GameComment.CreateFromEntity(c, token.UserId));
|
||||
|
||||
|
@ -164,15 +169,15 @@ public class CommentController : ControllerBase
|
|||
bool canDelete;
|
||||
if (comment.Type == CommentType.Profile)
|
||||
{
|
||||
canDelete = comment.PosterUserId == token.UserId || comment.TargetId == token.UserId;
|
||||
canDelete = comment.PosterUserId == token.UserId || comment.TargetUserId == token.UserId;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (slotType == "developer") slotId = await SlotHelper.GetPlaceholderSlotId(this.database, slotId, SlotType.Developer);
|
||||
|
||||
if (slotId != comment.TargetId) return this.BadRequest();
|
||||
if (slotId != comment.TargetSlotId) return this.BadRequest();
|
||||
|
||||
int slotCreator = await this.database.Slots.Where(s => s.SlotId == comment.TargetId)
|
||||
int slotCreator = await this.database.Slots.Where(s => s.SlotId == comment.TargetSlotId)
|
||||
.Where(s => s.CommentsEnabled)
|
||||
.Select(s => s.CreatorId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
|
|
@ -59,13 +59,13 @@ public class ModerationRemovalController : ControllerBase
|
|||
switch (comment.Type)
|
||||
{
|
||||
case CommentType.Level:
|
||||
int slotCreatorId = await this.database.Slots.Where(s => s.SlotId == comment.TargetId)
|
||||
int slotCreatorId = await this.database.Slots.Where(s => s.SlotId == comment.TargetSlotId)
|
||||
.Select(s => s.CreatorId)
|
||||
.FirstOrDefaultAsync();
|
||||
canDelete = user.UserId == comment.PosterUserId || user.UserId == slotCreatorId;
|
||||
break;
|
||||
case CommentType.Profile:
|
||||
canDelete = user.UserId == comment.PosterUserId || user.UserId == comment.TargetId;
|
||||
canDelete = user.UserId == comment.PosterUserId || user.UserId == comment.TargetUserId;
|
||||
break;
|
||||
default: throw new ArgumentOutOfRangeException(nameof(commentId));
|
||||
}
|
||||
|
|
|
@ -57,9 +57,9 @@ public class SlotPage : BaseLayout
|
|||
this.CommentsEnabled = ServerConfiguration.Instance.UserGeneratedContentLimits.LevelCommentsEnabled && this.Slot.CommentsEnabled;
|
||||
if (this.CommentsEnabled)
|
||||
{
|
||||
this.Comments = await this.Database.Comments.Include(p => p.Poster)
|
||||
.OrderByDescending(p => p.Timestamp)
|
||||
.Where(c => c.TargetId == id && c.Type == CommentType.Level)
|
||||
this.Comments = await this.Database.Comments.Include(c => c.Poster)
|
||||
.OrderByDescending(c => c.Timestamp)
|
||||
.Where(c => c.Type == CommentType.Level && c.TargetSlotId == id)
|
||||
.Where(c => !blockedUsers.Contains(c.PosterUserId))
|
||||
.Include(c => c.Poster)
|
||||
.Where(c => c.Poster.PermissionLevel != PermissionLevel.Banned)
|
||||
|
|
|
@ -96,7 +96,7 @@ public class UserPage : BaseLayout
|
|||
|
||||
this.Comments = await this.Database.Comments.Include(p => p.Poster)
|
||||
.OrderByDescending(p => p.Timestamp)
|
||||
.Where(p => p.TargetId == userId && p.Type == CommentType.Profile)
|
||||
.Where(p => p.TargetUserId == userId && p.Type == CommentType.Profile)
|
||||
.Where(p => !blockedUsers.Contains(p.PosterUserId))
|
||||
.Take(50)
|
||||
.ToDictionaryAsync(c => c, _ => (RatedCommentEntity?)null);
|
||||
|
|
|
@ -89,17 +89,15 @@ public partial class DatabaseContext
|
|||
if (await this.IsUserBlockedBy(userId, creatorId)) return false;
|
||||
}
|
||||
|
||||
this.Comments.Add
|
||||
(
|
||||
new CommentEntity
|
||||
this.Comments.Add(new CommentEntity
|
||||
{
|
||||
PosterUserId = userId,
|
||||
TargetId = targetId,
|
||||
TargetUserId = type == CommentType.Profile ? targetId : null,
|
||||
TargetSlotId = type == CommentType.Level ? targetId : null,
|
||||
Type = type,
|
||||
Message = message,
|
||||
Timestamp = TimeHelper.TimestampMillis,
|
||||
}
|
||||
);
|
||||
});
|
||||
await this.SaveChangesAsync();
|
||||
|
||||
return true;
|
||||
|
|
|
@ -59,7 +59,6 @@ namespace ProjectLighthouse.Migrations
|
|||
table: "Slots");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
using LBPUnion.ProjectLighthouse.Database;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ProjectLighthouse.Migrations
|
||||
{
|
||||
[DbContext(typeof(DatabaseContext))]
|
||||
[Migration("20230714212153_AddUserIdAndSlotIdToComment")]
|
||||
public partial class AddUserIdAndSlotIdToComment : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "TargetSlotId",
|
||||
table: "Comments",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "TargetUserId",
|
||||
table: "Comments",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
// Set SlotId and UserId to null if there isn't an existing slot or user
|
||||
migrationBuilder.Sql("UPDATE Comments AS c INNER JOIN Users AS u ON c.TargetId = u.UserId AND c.Type = 0 SET c.TargetUserId = u.UserId");
|
||||
migrationBuilder.Sql("UPDATE Comments AS c INNER JOIN Slots AS s ON c.TargetId = s.SlotId AND c.Type = 1 SET c.TargetSlotId = s.SlotId");
|
||||
|
||||
// Delete rows that have null SlotIds or UserIds
|
||||
migrationBuilder.Sql("DELETE FROM Comments WHERE TargetUserId IS NULL AND TargetSlotId IS NULL");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "TargetSlotId",
|
||||
table: "Comments");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "TargetUserId",
|
||||
table: "Comments");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
using LBPUnion.ProjectLighthouse.Database;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ProjectLighthouse.Migrations
|
||||
{
|
||||
[DbContext(typeof(DatabaseContext))]
|
||||
[Migration("20230714212234_AddForeignKeyConstraintToComment")]
|
||||
public partial class AddForeignKeyConstraintToComment : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "TargetId",
|
||||
table: "Comments");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Comments_TargetSlotId",
|
||||
table: "Comments",
|
||||
column: "TargetSlotId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Comments_TargetUserId",
|
||||
table: "Comments",
|
||||
column: "TargetUserId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Comments_Slots_TargetSlotId",
|
||||
table: "Comments",
|
||||
column: "TargetSlotId",
|
||||
principalTable: "Slots",
|
||||
principalColumn: "SlotId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Comments_Users_TargetUserId",
|
||||
table: "Comments",
|
||||
column: "TargetUserId",
|
||||
principalTable: "Users",
|
||||
principalColumn: "UserId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Comments_Slots_TargetSlotId",
|
||||
table: "Comments");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Comments_Users_TargetUserId",
|
||||
table: "Comments");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Comments_TargetSlotId",
|
||||
table: "Comments");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Comments_TargetUserId",
|
||||
table: "Comments");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "TargetId",
|
||||
table: "Comments",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -640,7 +640,10 @@ namespace ProjectLighthouse.Migrations
|
|||
b.Property<int>("PosterUserId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("TargetId")
|
||||
b.Property<int?>("TargetSlotId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("TargetUserId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("ThumbsDown")
|
||||
|
@ -659,6 +662,10 @@ namespace ProjectLighthouse.Migrations
|
|||
|
||||
b.HasIndex("PosterUserId");
|
||||
|
||||
b.HasIndex("TargetSlotId");
|
||||
|
||||
b.HasIndex("TargetUserId");
|
||||
|
||||
b.ToTable("Comments");
|
||||
});
|
||||
|
||||
|
@ -1325,7 +1332,19 @@ namespace ProjectLighthouse.Migrations
|
|||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Level.SlotEntity", "TargetSlot")
|
||||
.WithMany()
|
||||
.HasForeignKey("TargetSlotId");
|
||||
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.UserEntity", "TargetUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("TargetUserId");
|
||||
|
||||
b.Navigation("Poster");
|
||||
|
||||
b.Navigation("TargetSlot");
|
||||
|
||||
b.Navigation("TargetUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Profile.LastContactEntity", b =>
|
||||
|
|
|
@ -2,6 +2,7 @@ using System.ComponentModel.DataAnnotations;
|
|||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using LBPUnion.ProjectLighthouse.Database;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
||||
|
||||
|
@ -18,11 +19,23 @@ public class CommentEntity
|
|||
|
||||
public int PosterUserId { get; set; }
|
||||
|
||||
public int TargetId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(PosterUserId))]
|
||||
public UserEntity Poster { get; set; }
|
||||
|
||||
public CommentType Type { get; set; }
|
||||
|
||||
#nullable enable
|
||||
public int? TargetSlotId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(TargetSlotId))]
|
||||
public SlotEntity? TargetSlot { get; set; }
|
||||
|
||||
public int? TargetUserId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(TargetUserId))]
|
||||
public UserEntity? TargetUser { get; set; }
|
||||
#nullable disable
|
||||
|
||||
public bool Deleted { get; set; }
|
||||
|
||||
public string DeletedType { get; set; }
|
||||
|
@ -33,29 +46,25 @@ public class CommentEntity
|
|||
|
||||
public string Message { get; set; }
|
||||
|
||||
public CommentType Type { get; set; }
|
||||
|
||||
public int ThumbsUp { get; set; }
|
||||
public int ThumbsDown { get; set; }
|
||||
|
||||
public string GetCommentMessage(DatabaseContext database)
|
||||
{
|
||||
if (!this.Deleted)
|
||||
{
|
||||
return this.Message;
|
||||
}
|
||||
if (!this.Deleted) return this.Message;
|
||||
|
||||
if (this.DeletedBy == this.Poster.Username)
|
||||
{
|
||||
return "This comment has been deleted by the author.";
|
||||
}
|
||||
if (this.DeletedBy == this.Poster.Username) return "This comment has been deleted by the author.";
|
||||
|
||||
UserEntity deletedBy = database.Users.FirstOrDefault(u => u.Username == this.DeletedBy);
|
||||
|
||||
if (deletedBy != null && deletedBy.UserId == this.TargetId)
|
||||
{
|
||||
if (deletedBy == null) return "This comment has been deleted.";
|
||||
|
||||
// If the owner of the comment section deletes
|
||||
if (deletedBy.UserId == this.TargetUserId || deletedBy.UserId == database.Slots.Find(this.TargetSlotId)?.CreatorId)
|
||||
return "This comment has been deleted by the player.";
|
||||
}
|
||||
|
||||
if (this.DeletedType == "moderator" && deletedBy.IsModerator)
|
||||
return "This comment has been deleted by a moderator.";
|
||||
|
||||
return "This comment has been deleted.";
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ public class GameDeveloperSlot : SlotBase, INeedsPreparationForSerialization
|
|||
var stats = await database.Slots.Where(s => s.SlotId == this.SlotId)
|
||||
.Select(_ => new
|
||||
{
|
||||
CommentCount = database.Comments.Count(c => c.TargetId == this.SlotId && c.Type == CommentType.Level),
|
||||
CommentCount = database.Comments.Count(c => c.Type == CommentType.Level && c.TargetSlotId == this.SlotId),
|
||||
PhotoCount = database.Photos.Count(p => p.SlotId == this.SlotId),
|
||||
})
|
||||
.OrderBy(_ => 1)
|
||||
|
|
|
@ -168,7 +168,7 @@ public class GameUser : ILbpSerializable, INeedsPreparationForSerialization
|
|||
BonusSlots = database.Users.Where(u => u.UserId == this.UserId).Select(u => u.AdminGrantedSlots).First(),
|
||||
PlaylistCount = database.Playlists.Count(p => p.CreatorId == this.UserId),
|
||||
ReviewCount = database.Reviews.Count(r => r.ReviewerId == this.UserId),
|
||||
CommentCount = database.Comments.Count(c => c.TargetId == this.UserId && c.Type == CommentType.Profile),
|
||||
CommentCount = database.Comments.Count(c => c.TargetUserId == this.UserId),
|
||||
HeartCount = database.HeartedProfiles.Count(h => h.HeartedUserId == this.UserId),
|
||||
PhotosByMeCount = database.Photos.Count(p => p.CreatorId == this.UserId),
|
||||
PhotosWithMeCount = database.Photos.Include(p => p.PhotoSubjects)
|
||||
|
|
|
@ -11,7 +11,6 @@ using LBPUnion.ProjectLighthouse.Files;
|
|||
using LBPUnion.ProjectLighthouse.Helpers;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Interaction;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
||||
using LBPUnion.ProjectLighthouse.Types.Levels;
|
||||
using LBPUnion.ProjectLighthouse.Types.Misc;
|
||||
using LBPUnion.ProjectLighthouse.Types.Users;
|
||||
|
@ -241,7 +240,7 @@ public class GameUserSlot : SlotBase, INeedsPreparationForSerialization
|
|||
ThumbsUp = database.RatedLevels.Count(r => r.SlotId == this.SlotId && r.Rating == 1),
|
||||
ThumbsDown = database.RatedLevels.Count(r => r.SlotId == this.SlotId && r.Rating == -1),
|
||||
ReviewCount = database.Reviews.Count(r => r.SlotId == this.SlotId),
|
||||
CommentCount = database.Comments.Count(c => c.TargetId == this.SlotId && c.Type == CommentType.Level),
|
||||
CommentCount = database.Comments.Count(c => c.TargetSlotId == this.SlotId),
|
||||
PhotoCount = database.Photos.Count(p => p.SlotId == this.SlotId),
|
||||
AuthorPhotoCount = database.Photos.Count(p => p.SlotId == this.SlotId && p.CreatorId == this.CreatorId),
|
||||
HeartCount = database.HeartedLevels.Count(h => h.SlotId == this.SlotId),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue