[backend/masto-api] Enforce renote/reply visibility for notifications
This commit is contained in:
parent
4d7d8ee34e
commit
b4fea308f7
4 changed files with 46 additions and 12 deletions
|
@ -50,6 +50,7 @@ public class NotificationController(DatabaseContext db, NotificationRenderer not
|
||||||
.FilterBlocked(p => p.Notifier, user)
|
.FilterBlocked(p => p.Notifier, user)
|
||||||
.FilterBlocked(p => p.Note, user)
|
.FilterBlocked(p => p.Note, user)
|
||||||
.Paginate(query, ControllerContext)
|
.Paginate(query, ControllerContext)
|
||||||
|
.PrecomputeNoteVisibilities(user)
|
||||||
.RenderAllForMastodonAsync(notificationRenderer, user);
|
.RenderAllForMastodonAsync(notificationRenderer, user);
|
||||||
|
|
||||||
//TODO: handle mutes
|
//TODO: handle mutes
|
||||||
|
@ -69,12 +70,13 @@ public class NotificationController(DatabaseContext db, NotificationRenderer not
|
||||||
.IncludeCommonProperties()
|
.IncludeCommonProperties()
|
||||||
.Where(p => p.Notifiee == user && p.Id == id)
|
.Where(p => p.Notifiee == user && p.Id == id)
|
||||||
.EnsureNoteVisibilityFor(p => p.Note, user)
|
.EnsureNoteVisibilityFor(p => p.Note, user)
|
||||||
|
.PrecomputeNoteVisibilities(user)
|
||||||
.FirstOrDefaultAsync() ??
|
.FirstOrDefaultAsync() ??
|
||||||
throw GracefulException.RecordNotFound();
|
throw GracefulException.RecordNotFound();
|
||||||
|
|
||||||
//TODO: handle reply/renote visibility
|
//TODO: handle reply/renote visibility
|
||||||
|
|
||||||
var res = await notificationRenderer.RenderAsync(notification, user);
|
var res = await notificationRenderer.RenderAsync(notification.EnforceRenoteReplyVisibility(p => p.Note), user);
|
||||||
|
|
||||||
return Ok(res);
|
return Ok(res);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,19 +18,14 @@ public class NotificationRenderer(NoteRenderer noteRenderer, UserRenderer userRe
|
||||||
? notification.Note?.Renote
|
? notification.Note?.Renote
|
||||||
: notification.Note;
|
: notification.Note;
|
||||||
|
|
||||||
if (notification.Note != null && targetNote == null)
|
var note = targetNote != null
|
||||||
throw new Exception("targetNote must not be null at this stage");
|
? statuses?.FirstOrDefault(p => p.Id == targetNote.Id) ??
|
||||||
|
await noteRenderer.RenderAsync(targetNote, user, accounts)
|
||||||
var note = notification.Note != null
|
|
||||||
? statuses?.FirstOrDefault(p => p.Id == targetNote!.Id) ??
|
|
||||||
await noteRenderer.RenderAsync(targetNote!, user, accounts)
|
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
var notifier = accounts?.FirstOrDefault(p => p.Id == dbNotifier.Id) ??
|
var notifier = accounts?.FirstOrDefault(p => p.Id == dbNotifier.Id) ??
|
||||||
await userRenderer.RenderAsync(dbNotifier);
|
await userRenderer.RenderAsync(dbNotifier);
|
||||||
|
|
||||||
//TODO: specially handle quotes
|
|
||||||
|
|
||||||
var res = new NotificationEntity
|
var res = new NotificationEntity
|
||||||
{
|
{
|
||||||
Id = notification.Id,
|
Id = notification.Id,
|
||||||
|
|
|
@ -125,4 +125,10 @@ public class Notification : IEntity
|
||||||
[Column("id")]
|
[Column("id")]
|
||||||
[StringLength(32)]
|
[StringLength(32)]
|
||||||
public string Id { get; set; } = null!;
|
public string Id { get; set; } = null!;
|
||||||
|
|
||||||
|
public Notification WithPrecomputedNoteVisibilities(bool reply, bool renote)
|
||||||
|
{
|
||||||
|
Note = Note?.WithPrecomputedVisibilities(reply, renote);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -176,6 +176,16 @@ public static class QueryableExtensions
|
||||||
p.Renote.IsVisibleFor(user)));
|
p.Renote.IsVisibleFor(user)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IQueryable<Notification> PrecomputeNoteVisibilities(this IQueryable<Notification> query, User user)
|
||||||
|
{
|
||||||
|
return query.Select(p => p.WithPrecomputedNoteVisibilities(p.Note != null &&
|
||||||
|
p.Note.Reply != null &&
|
||||||
|
p.Note.Reply.IsVisibleFor(user),
|
||||||
|
p.Note != null &&
|
||||||
|
p.Note.Renote != null &&
|
||||||
|
p.Note.Renote.IsVisibleFor(user)));
|
||||||
|
}
|
||||||
|
|
||||||
public static IQueryable<User> PrecomputeRelationshipData(this IQueryable<User> query, User user)
|
public static IQueryable<User> PrecomputeRelationshipData(this IQueryable<User> query, User user)
|
||||||
{
|
{
|
||||||
return query.Select(p => p.WithPrecomputedBlockStatus(p.IsBlocking(user), p.IsBlockedBy(user))
|
return query.Select(p => p.WithPrecomputedBlockStatus(p.IsBlocking(user), p.IsBlockedBy(user))
|
||||||
|
@ -248,13 +258,32 @@ public static class QueryableExtensions
|
||||||
return list.Select(EnforceRenoteReplyVisibility);
|
return list.Select(EnforceRenoteReplyVisibility);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static T EnforceRenoteReplyVisibility<T>(this T source, Expression<Func<T, Note?>> predicate)
|
||||||
|
{
|
||||||
|
var note = predicate.Compile().Invoke(source);
|
||||||
|
if (note == null) return source;
|
||||||
|
if (!note.PrecomputedIsReplyVisible ?? false)
|
||||||
|
note.Reply = null;
|
||||||
|
if (!note.PrecomputedIsRenoteVisible ?? false)
|
||||||
|
note.Renote = null;
|
||||||
|
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<T> EnforceRenoteReplyVisibility<T>(
|
||||||
|
this IEnumerable<T> list, Expression<Func<T, Note?>> predicate
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return list.Select(p => EnforceRenoteReplyVisibility(p, predicate));
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task<List<StatusEntity>> RenderAllForMastodonAsync(
|
public static async Task<List<StatusEntity>> RenderAllForMastodonAsync(
|
||||||
this IQueryable<Note> notes, NoteRenderer renderer, User? user
|
this IQueryable<Note> notes, NoteRenderer renderer, User? user
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var list = (await notes.ToListAsync())
|
var list = (await notes.ToListAsync())
|
||||||
.EnforceRenoteReplyVisibility()
|
.EnforceRenoteReplyVisibility()
|
||||||
.ToList();
|
.ToList();
|
||||||
return (await renderer.RenderManyAsync(list, user)).ToList();
|
return (await renderer.RenderManyAsync(list, user)).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +299,9 @@ public static class QueryableExtensions
|
||||||
this IQueryable<Notification> notifications, NotificationRenderer renderer, User user
|
this IQueryable<Notification> notifications, NotificationRenderer renderer, User user
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var list = await notifications.ToListAsync();
|
var list = (await notifications.ToListAsync())
|
||||||
|
.EnforceRenoteReplyVisibility(p => p.Note)
|
||||||
|
.ToList();
|
||||||
return (await renderer.RenderManyAsync(list, user)).ToList();
|
return (await renderer.RenderManyAsync(list, user)).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue