mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-05-15 06:02:28 +00:00
Profile Blocking (#662)
* Added blocked user DB object
* Added user blocking functions
* Fixed DB Migration
* Updated DB Functions
* Added blocked user support to website
* Fixed DB Migration
* I forgot to save 🫠
* More migration pain
* Fixed Unblock label
* Update ProjectLighthouse.Servers.Website/Pages/UserPage.cshtml
sounds cool
Co-authored-by: koko <68549366+sudokoko@users.noreply.github.com>
* Removed unnecessary imports in database
* Removed unnecessary imports in UserPage.cshtml.cs
* Made comments in-game respect blocked users
* Update ProjectLighthouse/Database.cs
Co-authored-by: Josh <josh@slendy.pw>
* Update ProjectLighthouse/Database.cs
Co-authored-by: Josh <josh@slendy.pw>
* DB Code cleanup
* Cleaned up userPage block detection code
* Get only the creator id in lieu of the whole object
* Fixed null condition when not logged in
* Fixed null condition when not logged in
* Potential DB Optimisation
* Apply suggestions from code review
Co-authored-by: Josh <josh@slendy.pw>
* Fix errors and null warning
* Use explicit type in lieu of var
* changed block icons
* Optimize blocked user check and save changes when unblocking
---------
Co-authored-by: koko <68549366+sudokoko@users.noreply.github.com>
Co-authored-by: Josh <josh@slendy.pw>
This commit is contained in:
parent
b4326d4798
commit
3fcfaaf5cc
8 changed files with 227 additions and 8 deletions
|
@ -71,9 +71,15 @@ public class CommentController : ControllerBase
|
|||
|
||||
if (targetId == 0) return this.NotFound();
|
||||
|
||||
List<Comment> comments = await this.database.Comments.Include
|
||||
(c => c.Poster)
|
||||
.Where(c => c.TargetId == targetId && c.Type == type)
|
||||
List<int> blockedUsers = await (
|
||||
from blockedProfile in this.database.BlockedProfiles
|
||||
where blockedProfile.UserId == token.UserId
|
||||
select blockedProfile.BlockedUserId
|
||||
).ToListAsync();
|
||||
|
||||
List<Comment> comments = await this.database.Comments.Include(c => c.Poster)
|
||||
.Where(c => c.TargetId == targetId && c.Type == type && !c.Poster.IsBanned)
|
||||
.Where(c => !blockedUsers.Contains(c.PosterUserId))
|
||||
.OrderByDescending(c => c.Timestamp)
|
||||
.Skip(Math.Max(0, pageStart - 1))
|
||||
.Take(Math.Min(pageSize, 30))
|
||||
|
|
|
@ -87,4 +87,32 @@ public class UserPageController : ControllerBase
|
|||
|
||||
return this.Redirect("~/user/" + id);
|
||||
}
|
||||
|
||||
[HttpGet("block")]
|
||||
public async Task<IActionResult> BlockUser([FromRoute] int id)
|
||||
{
|
||||
WebToken? token = this.database.WebTokenFromRequest(this.Request);
|
||||
if (token == null) return this.Redirect("~/login");
|
||||
|
||||
User? blockedUser = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == id);
|
||||
if (blockedUser == null) return this.NotFound();
|
||||
|
||||
await this.database.BlockUser(token.UserId, blockedUser);
|
||||
|
||||
return this.Redirect("~/user/" + id);
|
||||
}
|
||||
|
||||
[HttpGet("unblock")]
|
||||
public async Task<IActionResult> UnblockUser([FromRoute] int id)
|
||||
{
|
||||
WebToken? token = this.database.WebTokenFromRequest(this.Request);
|
||||
if (token == null) return this.Redirect("~/login");
|
||||
|
||||
User? blockedUser = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == id);
|
||||
if (blockedUser == null) return this.NotFound();
|
||||
|
||||
await this.database.UnblockUser(token.UserId, blockedUser);
|
||||
|
||||
return this.Redirect("~/user/" + id);
|
||||
}
|
||||
}
|
|
@ -61,6 +61,20 @@
|
|||
<br>
|
||||
@if (Model.ProfileUser != Model.User && Model.User != null)
|
||||
{
|
||||
if (!Model.IsProfileUserBlocked)
|
||||
{
|
||||
<a class="ui red button" href="/user/@Model.ProfileUser.UserId/block">
|
||||
<i class="user alternate slash icon"></i>
|
||||
<span>Block</span>
|
||||
</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<a class="ui black button" href="/user/@Model.ProfileUser.UserId/unblock">
|
||||
<i class="user alternate icon"></i>
|
||||
<span>Unblock</span>
|
||||
</a>
|
||||
}
|
||||
if (!Model.IsProfileUserHearted)
|
||||
{
|
||||
<a class="ui pink button" href="/user/@Model.ProfileUser.UserId/heart">
|
||||
|
|
|
@ -18,6 +18,8 @@ public class UserPage : BaseLayout
|
|||
|
||||
public bool IsProfileUserHearted;
|
||||
|
||||
public bool IsProfileUserBlocked;
|
||||
|
||||
public List<Photo>? Photos;
|
||||
public List<Slot>? Slots;
|
||||
|
||||
|
@ -86,11 +88,18 @@ public class UserPage : BaseLayout
|
|||
}
|
||||
|
||||
this.CommentsEnabled = ServerConfiguration.Instance.UserGeneratedContentLimits.LevelCommentsEnabled && this.ProfileUser.CommentsEnabled;
|
||||
|
||||
if (this.CommentsEnabled)
|
||||
{
|
||||
List<int> blockedUsers = this.User == null ? new List<int>() : await
|
||||
(from blockedProfile in this.Database.BlockedProfiles
|
||||
where blockedProfile.UserId == this.User.UserId
|
||||
select blockedProfile.BlockedUserId).ToListAsync();
|
||||
|
||||
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 => !blockedUsers.Contains(p.PosterUserId))
|
||||
.Take(50)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
@ -114,6 +123,8 @@ public class UserPage : BaseLayout
|
|||
.Where(h => h.UserId == this.User.UserId)
|
||||
.AnyAsync();
|
||||
|
||||
this.IsProfileUserBlocked = await this.Database.IsUserBlockedBy(this.ProfileUser.UserId, this.User.UserId);
|
||||
|
||||
return this.Page();
|
||||
}
|
||||
}
|
|
@ -53,6 +53,7 @@ public class Database : DbContext
|
|||
public DbSet<APIKey> APIKeys { get; set; }
|
||||
public DbSet<Playlist> Playlists { get; set; }
|
||||
public DbSet<PlatformLinkAttempt> PlatformLinkAttempts { get; set; }
|
||||
public DbSet<BlockedProfile> BlockedProfiles { get; set; }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder options)
|
||||
=> options.UseMySql(ServerConfiguration.Instance.DbConnectionString, MySqlServerVersion.LatestSupportedServerVersion);
|
||||
|
@ -131,9 +132,10 @@ public class Database : DbContext
|
|||
Comment? comment = await this.Comments.FirstOrDefaultAsync(c => commentId == c.CommentId);
|
||||
|
||||
if (comment == null) return false;
|
||||
|
||||
if (comment.PosterUserId == userId) return false;
|
||||
|
||||
if (await this.IsUserBlockedBy(userId, comment.PosterUserId)) return false;
|
||||
|
||||
Reaction? reaction = await this.Reactions.FirstOrDefaultAsync(r => r.UserId == userId && r.TargetId == commentId);
|
||||
if (reaction == null)
|
||||
{
|
||||
|
@ -189,14 +191,17 @@ public class Database : DbContext
|
|||
.Select(u => u.UserId)
|
||||
.FirstOrDefaultAsync();
|
||||
if (targetUserId == 0) return false;
|
||||
if (await this.IsUserBlockedBy(userId, targetUserId)) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int targetSlotId = await this.Slots.Where(s => s.SlotId == targetId)
|
||||
int creatorId = await this.Slots.Where(s => s.SlotId == targetId)
|
||||
.Where(s => s.CommentsEnabled && !s.Hidden)
|
||||
.Select(s => s.SlotId)
|
||||
.Select(s => s.CreatorId)
|
||||
.FirstOrDefaultAsync();
|
||||
if (targetSlotId == 0) return false;
|
||||
if (creatorId == 0) return false;
|
||||
|
||||
if (await this.IsUserBlockedBy(userId, creatorId)) return false;
|
||||
}
|
||||
|
||||
this.Comments.Add
|
||||
|
@ -312,6 +317,39 @@ public class Database : DbContext
|
|||
await this.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task BlockUser(int userId, User blockedUser)
|
||||
{
|
||||
if (userId == blockedUser.UserId) return;
|
||||
|
||||
User? user = await this.Users.FindAsync(userId);
|
||||
|
||||
BlockedProfile blockedProfile = new()
|
||||
{
|
||||
User = user,
|
||||
BlockedUser = blockedUser,
|
||||
};
|
||||
|
||||
await this.BlockedProfiles.AddAsync(blockedProfile);
|
||||
|
||||
await this.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task UnblockUser(int userId, User blockedUser)
|
||||
{
|
||||
if (userId == blockedUser.UserId) return;
|
||||
|
||||
this.BlockedProfiles.RemoveWhere(bp => bp.BlockedUserId == blockedUser.UserId && bp.UserId == userId);
|
||||
|
||||
await this.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> IsUserBlockedBy(int userId, int targetId)
|
||||
{
|
||||
if (targetId == userId) return false;
|
||||
|
||||
return await this.BlockedProfiles.Has(bp => bp.BlockedUserId == userId && bp.UserId == targetId);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region User Helper Methods
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
using LBPUnion.ProjectLighthouse;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ProjectLighthouse.Migrations
|
||||
{
|
||||
|
||||
[DbContext(typeof(Database))]
|
||||
[Migration("20230208165011_AddedUserBlocking")]
|
||||
public partial class AddedUserBlocking : Migration
|
||||
{
|
||||
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "BlockedProfiles",
|
||||
columns: table => new
|
||||
{
|
||||
BlockedProfileId = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
UserId = table.Column<int>(type: "int", nullable: false),
|
||||
BlockedUserId = table.Column<int>(type: "int", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_BlockedProfiles", x => x.BlockedProfileId);
|
||||
table.ForeignKey(
|
||||
name: "FK_BlockedProfiles_Users_BlockedUserId",
|
||||
column: x => x.BlockedUserId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "UserId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_BlockedProfiles_Users_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "UserId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_BlockedProfiles_BlockedUserId",
|
||||
table: "BlockedProfiles",
|
||||
column: "BlockedUserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_BlockedProfiles_UserId",
|
||||
table: "BlockedProfiles",
|
||||
column: "UserId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "BlockedProfiles");
|
||||
}
|
||||
}
|
||||
}
|
20
ProjectLighthouse/PlayerData/Profiles/BlockedProfile.cs
Normal file
20
ProjectLighthouse/PlayerData/Profiles/BlockedProfile.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.PlayerData.Profiles;
|
||||
|
||||
public class BlockedProfile
|
||||
{
|
||||
[Key]
|
||||
public int BlockedProfileId { get; set; }
|
||||
|
||||
public int UserId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(UserId))]
|
||||
public User User { get; set; }
|
||||
|
||||
public int BlockedUserId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(BlockedUserId))]
|
||||
public User BlockedUser { get; set; }
|
||||
}
|
|
@ -609,6 +609,27 @@ namespace ProjectLighthouse.Migrations
|
|||
b.ToTable("PlatformLinkAttempts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Profiles.BlockedProfile", b =>
|
||||
{
|
||||
b.Property<int>("BlockedProfileId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("BlockedUserId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("BlockedProfileId");
|
||||
|
||||
b.HasIndex("BlockedUserId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("BlockedProfiles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Profiles.Comment", b =>
|
||||
{
|
||||
b.Property<int>("CommentId")
|
||||
|
@ -1225,6 +1246,25 @@ namespace ProjectLighthouse.Migrations
|
|||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Profiles.BlockedProfile", b =>
|
||||
{
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "BlockedUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("BlockedUserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BlockedUser");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.PlayerData.Profiles.Comment", b =>
|
||||
{
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.PlayerData.Profiles.User", "Poster")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue