using System.Net; using System.Net.Mime; using Iceshrimp.Backend.Controllers.Mastodon.Attributes; using Iceshrimp.Backend.Controllers.Mastodon.Renderers; using Iceshrimp.Backend.Controllers.Mastodon.Schemas; using Iceshrimp.Backend.Controllers.Mastodon.Schemas.Entities; using Iceshrimp.Backend.Controllers.Shared.Attributes; using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Extensions; using Iceshrimp.Backend.Core.Middleware; using Iceshrimp.Backend.Core.Services; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.RateLimiting; using Microsoft.EntityFrameworkCore; namespace Iceshrimp.Backend.Controllers.Mastodon; [Route("/api/v1/reports")] [Authenticate] [MastodonApiController] [EnableCors("mastodon")] [EnableRateLimiting("sliding")] [Produces(MediaTypeNames.Application.Json)] public class ReportController(ReportService reportSvc, DatabaseContext db, UserRenderer userRenderer) : ControllerBase { [Authorize("write:reports")] [HttpPost] [ProducesResults(HttpStatusCode.OK)] [ProducesErrors(HttpStatusCode.BadRequest, HttpStatusCode.NotFound)] public async Task FileReport([FromHybrid] ReportSchemas.FileReportRequest request) { var user = HttpContext.GetUserOrFail(); if (request.Comment.Length > 2048) throw GracefulException.BadRequest("Comment length must not exceed 2048 characters"); if (request.AccountId == user.Id) throw GracefulException.BadRequest("You cannot report yourself"); var target = await db.Users.IncludeCommonProperties().FirstOrDefaultAsync(p => p.Id == request.AccountId) ?? throw GracefulException.NotFound("Target user not found"); var notes = await db.Notes.Where(p => request.StatusIds.Contains(p.Id)).ToListAsync(); if (notes.Any(p => p.UserId != target.Id)) throw GracefulException.BadRequest("Note author does not match target user"); var report = await reportSvc.CreateReportAsync(user, target, notes, request.Comment); var targetAccount = await userRenderer.RenderAsync(report.TargetUser, user); return new ReportEntity { Id = report.Id, Category = "other", Comment = report.Comment, Forwarded = report.Forwarded, ActionTaken = report.Resolved, CreatedAt = report.CreatedAt.ToStringIso8601Like(), TargetAccount = targetAccount, RuleIds = null, StatusIds = request.StatusIds, ActionTakenAt = null }; } }