feat(backend): report context, fix deleting reports
This commit is contained in:
parent
bd21eeebcf
commit
546e900204
9 changed files with 133 additions and 3 deletions
|
@ -18,6 +18,7 @@ using Foxnouns.Backend.Database.Models;
|
||||||
using Foxnouns.Backend.Dto;
|
using Foxnouns.Backend.Dto;
|
||||||
using Foxnouns.Backend.Middleware;
|
using Foxnouns.Backend.Middleware;
|
||||||
using Foxnouns.Backend.Services;
|
using Foxnouns.Backend.Services;
|
||||||
|
using Foxnouns.Backend.Utils;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
@ -49,6 +50,8 @@ public class ReportsController(
|
||||||
[FromBody] CreateReportRequest req
|
[FromBody] CreateReportRequest req
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
ValidationUtils.Validate([("context", ValidationUtils.ValidateReportContext(req.Context))]);
|
||||||
|
|
||||||
User target = await db.ResolveUserAsync(id);
|
User target = await db.ResolveUserAsync(id);
|
||||||
|
|
||||||
if (target.Id == CurrentUser!.Id)
|
if (target.Id == CurrentUser!.Id)
|
||||||
|
@ -96,6 +99,7 @@ public class ReportsController(
|
||||||
TargetUserId = target.Id,
|
TargetUserId = target.Id,
|
||||||
TargetMemberId = null,
|
TargetMemberId = null,
|
||||||
Reason = req.Reason,
|
Reason = req.Reason,
|
||||||
|
Context = req.Context,
|
||||||
TargetType = ReportTargetType.User,
|
TargetType = ReportTargetType.User,
|
||||||
TargetSnapshot = snapshot,
|
TargetSnapshot = snapshot,
|
||||||
};
|
};
|
||||||
|
@ -112,6 +116,8 @@ public class ReportsController(
|
||||||
[FromBody] CreateReportRequest req
|
[FromBody] CreateReportRequest req
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
ValidationUtils.Validate([("context", ValidationUtils.ValidateReportContext(req.Context))]);
|
||||||
|
|
||||||
Member target = await db.ResolveMemberAsync(id);
|
Member target = await db.ResolveMemberAsync(id);
|
||||||
|
|
||||||
if (target.User.Id == CurrentUser!.Id)
|
if (target.User.Id == CurrentUser!.Id)
|
||||||
|
@ -158,6 +164,7 @@ public class ReportsController(
|
||||||
TargetUserId = target.User.Id,
|
TargetUserId = target.User.Id,
|
||||||
TargetMemberId = target.Id,
|
TargetMemberId = target.Id,
|
||||||
Reason = req.Reason,
|
Reason = req.Reason,
|
||||||
|
Context = req.Context,
|
||||||
TargetType = ReportTargetType.Member,
|
TargetType = ReportTargetType.Member,
|
||||||
TargetSnapshot = snapshot,
|
TargetSnapshot = snapshot,
|
||||||
};
|
};
|
||||||
|
|
|
@ -108,6 +108,12 @@ public class DatabaseContext(DbContextOptions options) : DbContext(options)
|
||||||
.HasFilter("fediverse_application_id IS NULL")
|
.HasFilter("fediverse_application_id IS NULL")
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
|
|
||||||
|
modelBuilder
|
||||||
|
.Entity<AuditLogEntry>()
|
||||||
|
.HasOne(e => e.Report)
|
||||||
|
.WithOne(e => e.AuditLogEntry)
|
||||||
|
.OnDelete(DeleteBehavior.SetNull);
|
||||||
|
|
||||||
modelBuilder.Entity<User>().Property(u => u.Sid).HasDefaultValueSql("find_free_user_sid()");
|
modelBuilder.Entity<User>().Property(u => u.Sid).HasDefaultValueSql("find_free_user_sid()");
|
||||||
modelBuilder.Entity<User>().Property(u => u.Fields).HasColumnType("jsonb");
|
modelBuilder.Entity<User>().Property(u => u.Fields).HasColumnType("jsonb");
|
||||||
modelBuilder.Entity<User>().Property(u => u.Names).HasColumnType("jsonb");
|
modelBuilder.Entity<User>().Property(u => u.Names).HasColumnType("jsonb");
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Foxnouns.Backend.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
[DbContext(typeof(DatabaseContext))]
|
||||||
|
[Migration("20241218195457_AddContextToReports")]
|
||||||
|
public partial class AddContextToReports : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "context",
|
||||||
|
table: "reports",
|
||||||
|
type: "text",
|
||||||
|
nullable: true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(name: "context", table: "reports");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Foxnouns.Backend.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
[DbContext(typeof(DatabaseContext))]
|
||||||
|
[Migration("20241218201855_MakeAuditLogReportsNullable")]
|
||||||
|
public partial class MakeAuditLogReportsNullable : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "fk_audit_log_reports_report_id",
|
||||||
|
table: "audit_log"
|
||||||
|
);
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(name: "ix_audit_log_report_id", table: "audit_log");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_audit_log_report_id",
|
||||||
|
table: "audit_log",
|
||||||
|
column: "report_id",
|
||||||
|
unique: true
|
||||||
|
);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "fk_audit_log_reports_report_id",
|
||||||
|
table: "audit_log",
|
||||||
|
column: "report_id",
|
||||||
|
principalTable: "reports",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.SetNull
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "fk_audit_log_reports_report_id",
|
||||||
|
table: "audit_log"
|
||||||
|
);
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(name: "ix_audit_log_report_id", table: "audit_log");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_audit_log_report_id",
|
||||||
|
table: "audit_log",
|
||||||
|
column: "report_id"
|
||||||
|
);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "fk_audit_log_reports_report_id",
|
||||||
|
table: "audit_log",
|
||||||
|
column: "report_id",
|
||||||
|
principalTable: "reports",
|
||||||
|
principalColumn: "id"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -113,6 +113,7 @@ namespace Foxnouns.Backend.Database.Migrations
|
||||||
.HasName("pk_audit_log");
|
.HasName("pk_audit_log");
|
||||||
|
|
||||||
b.HasIndex("ReportId")
|
b.HasIndex("ReportId")
|
||||||
|
.IsUnique()
|
||||||
.HasDatabaseName("ix_audit_log_report_id");
|
.HasDatabaseName("ix_audit_log_report_id");
|
||||||
|
|
||||||
b.ToTable("audit_log", (string)null);
|
b.ToTable("audit_log", (string)null);
|
||||||
|
@ -409,6 +410,10 @@ namespace Foxnouns.Backend.Database.Migrations
|
||||||
.HasColumnType("bigint")
|
.HasColumnType("bigint")
|
||||||
.HasColumnName("id");
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
b.Property<string>("Context")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("context");
|
||||||
|
|
||||||
b.Property<int>("Reason")
|
b.Property<int>("Reason")
|
||||||
.HasColumnType("integer")
|
.HasColumnType("integer")
|
||||||
.HasColumnName("reason");
|
.HasColumnName("reason");
|
||||||
|
@ -675,8 +680,9 @@ namespace Foxnouns.Backend.Database.Migrations
|
||||||
modelBuilder.Entity("Foxnouns.Backend.Database.Models.AuditLogEntry", b =>
|
modelBuilder.Entity("Foxnouns.Backend.Database.Models.AuditLogEntry", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Foxnouns.Backend.Database.Models.Report", "Report")
|
b.HasOne("Foxnouns.Backend.Database.Models.Report", "Report")
|
||||||
.WithMany()
|
.WithOne("AuditLogEntry")
|
||||||
.HasForeignKey("ReportId")
|
.HasForeignKey("Foxnouns.Backend.Database.Models.AuditLogEntry", "ReportId")
|
||||||
|
.OnDelete(DeleteBehavior.SetNull)
|
||||||
.HasConstraintName("fk_audit_log_reports_report_id");
|
.HasConstraintName("fk_audit_log_reports_report_id");
|
||||||
|
|
||||||
b.Navigation("Report");
|
b.Navigation("Report");
|
||||||
|
@ -839,6 +845,11 @@ namespace Foxnouns.Backend.Database.Migrations
|
||||||
b.Navigation("ProfileFlags");
|
b.Navigation("ProfileFlags");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Foxnouns.Backend.Database.Models.Report", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("AuditLogEntry");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Foxnouns.Backend.Database.Models.User", b =>
|
modelBuilder.Entity("Foxnouns.Backend.Database.Models.User", b =>
|
||||||
{
|
{
|
||||||
b.Navigation("AuthMethods");
|
b.Navigation("AuthMethods");
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using Foxnouns.Backend.Utils;
|
using Foxnouns.Backend.Utils;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
|
|
@ -29,9 +29,12 @@ public class Report : BaseModel
|
||||||
|
|
||||||
public ReportStatus Status { get; set; }
|
public ReportStatus Status { get; set; }
|
||||||
public ReportReason Reason { get; init; }
|
public ReportReason Reason { get; init; }
|
||||||
|
public string? Context { get; init; }
|
||||||
|
|
||||||
public ReportTargetType TargetType { get; init; }
|
public ReportTargetType TargetType { get; init; }
|
||||||
public string? TargetSnapshot { get; init; }
|
public string? TargetSnapshot { get; init; }
|
||||||
|
|
||||||
|
public AuditLogEntry? AuditLogEntry { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonConverter(typeof(ScreamingSnakeCaseEnumConverter))]
|
[JsonConverter(typeof(ScreamingSnakeCaseEnumConverter))]
|
||||||
|
|
|
@ -57,7 +57,7 @@ public record NotificationResponse(
|
||||||
|
|
||||||
public record AuditLogEntity(Snowflake Id, string Username);
|
public record AuditLogEntity(Snowflake Id, string Username);
|
||||||
|
|
||||||
public record CreateReportRequest(ReportReason Reason);
|
public record CreateReportRequest(ReportReason Reason, string? Context = null);
|
||||||
|
|
||||||
public record IgnoreReportRequest(string? Reason = null);
|
public record IgnoreReportRequest(string? Reason = null);
|
||||||
|
|
||||||
|
|
|
@ -196,6 +196,13 @@ public static partial class ValidationUtils
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public const int MaximumReportContextLength = 512;
|
||||||
|
|
||||||
|
public static ValidationError? ValidateReportContext(string? context) =>
|
||||||
|
context?.Length > MaximumReportContextLength
|
||||||
|
? ValidationError.GenericValidationError("Avatar is too large", null)
|
||||||
|
: null;
|
||||||
|
|
||||||
public const int MinimumPasswordLength = 12;
|
public const int MinimumPasswordLength = 12;
|
||||||
public const int MaximumPasswordLength = 1024;
|
public const int MaximumPasswordLength = 1024;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue