[backend/masto-client] Implement note deletes

This commit is contained in:
Laura Hausmann 2024-02-18 23:50:11 +01:00
parent 6c90d0554e
commit 7a7f6cb527
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
4 changed files with 53 additions and 1 deletions

View file

@ -181,6 +181,7 @@ public class StatusController(
[Authorize("write:statuses")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(StatusEntity))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(MastodonErrorResponse))]
[ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(MastodonErrorResponse))]
public async Task<IActionResult> EditNote(string id, [FromHybrid] StatusSchemas.EditStatusRequest request)
{
var user = HttpContext.GetUserOrFail();
@ -202,4 +203,23 @@ public class StatusController(
return Ok(res);
}
[HttpDelete("{id}")]
[Authorize("write:statuses")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(StatusEntity))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(MastodonErrorResponse))]
[ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(MastodonErrorResponse))]
public async Task<IActionResult> DeleteNote(string id)
{
var user = HttpContext.GetUserOrFail();
var note = await db.Notes.IncludeCommonProperties().FirstOrDefaultAsync(p => p.Id == id && p.User == user) ??
throw GracefulException.RecordNotFound();
if (user.Id != note.UserId)
throw GracefulException.RecordNotFound();
var res = await noteRenderer.RenderAsync(note, user);
await noteSvc.DeleteNoteAsync(note);
return Ok(res);
}
}

View file

@ -34,6 +34,11 @@ public class ActivityRenderer(
Cc = obj.Cc
};
public ASDelete RenderDelete(ASActor actor, ASObject obj) => new()
{
Id = $"{obj.Id}#Delete", Actor = actor.Compact(), Object = obj
};
public ASAccept RenderAccept(User followee, User follower, string requestId) => new()
{
Id = GenerateActivityId(),

View file

@ -77,7 +77,10 @@ public class ASObject : ASObjectBase
}
}
public class ASTombstone : ASObject;
public class ASTombstone : ASObject
{
public ASTombstone() => Type = Types.Tombstone;
}
public sealed class StringListSingleConverter : ASSerializer.ListSingleObjectConverter<string>;

View file

@ -198,6 +198,30 @@ public class NoteService(
return note;
}
public async Task DeleteNoteAsync(Note note)
{
note.User.NotesCount--;
db.Update(note.User);
db.Remove(note);
eventSvc.RaiseNoteDeleted(this, note);
await db.SaveChangesAsync();
if (note.UserHost != null)
return;
var recipients = await db.Users.Where(p => note.Mentions.Concat(note.VisibleUserIds).Distinct().Contains(p.Id))
.Select(p => new User { Host = p.Host, Inbox = p.Inbox })
.ToListAsync();
var actor = userRenderer.RenderLite(note.User);
var activity = activityRenderer.RenderDelete(actor, new ASTombstone { Id = note.GetPublicUri(config.Value) });
if (note.Visibility == Note.NoteVisibility.Specified)
await deliverSvc.DeliverToAsync(activity, note.User, recipients.ToArray());
else
await deliverSvc.DeliverToFollowersAsync(activity, note.User, recipients);
}
public async Task DeleteNoteAsync(ASTombstone note, ASActor actor)
{
// ReSharper disable once EntityFramework.NPlusOne.IncompleteDataQuery (it doesn't know about IncludeCommonProperties())