From d3da11f827bdad0016817e8ea485609de18c3fd7 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Sat, 3 Feb 2024 04:05:48 +0100 Subject: [PATCH] [backend/masto-client] Fix concurrent DbContext access --- .../Controllers/Mastodon/Renderers/NoteRenderer.cs | 7 +++++++ .../Controllers/Mastodon/Renderers/UserRenderer.cs | 3 +-- Iceshrimp.Backend/Core/Extensions/QueryableExtensions.cs | 9 +++------ .../Core/Middleware/AuthenticationMiddleware.cs | 8 ++++++-- .../Core/Middleware/OauthAuthenticationMiddleware.cs | 1 + 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NoteRenderer.cs b/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NoteRenderer.cs index 7a7d09b1..3c5a7908 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NoteRenderer.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NoteRenderer.cs @@ -1,7 +1,10 @@ +using System.Collections; using Iceshrimp.Backend.Controllers.Mastodon.Schemas.Entities; using Iceshrimp.Backend.Core.Configuration; using Iceshrimp.Backend.Core.Database.Tables; +using Iceshrimp.Backend.Core.Extensions; using Iceshrimp.Backend.Core.Helpers.LibMfm.Conversion; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; namespace Iceshrimp.Backend.Controllers.Mastodon.Renderers; @@ -42,4 +45,8 @@ public class NoteRenderer(IOptions config, UserRenderer return res; } + + public async Task> RenderManyAsync(IEnumerable notes) { + return await notes.Select(RenderAsync).AwaitAllAsync(); + } } \ No newline at end of file diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Renderers/UserRenderer.cs b/Iceshrimp.Backend/Controllers/Mastodon/Renderers/UserRenderer.cs index 8407fa1c..92fd263c 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/Renderers/UserRenderer.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/Renderers/UserRenderer.cs @@ -44,7 +44,6 @@ public class UserRenderer(IOptions config, DatabaseConte } public async Task RenderAsync(User user) { - var profile = await db.UserProfiles.FirstOrDefaultAsync(p => p.User == user); - return await RenderAsync(user, profile); + return await RenderAsync(user, user.UserProfile); } } \ No newline at end of file diff --git a/Iceshrimp.Backend/Core/Extensions/QueryableExtensions.cs b/Iceshrimp.Backend/Core/Extensions/QueryableExtensions.cs index 99e7613f..96429bc1 100644 --- a/Iceshrimp.Backend/Core/Extensions/QueryableExtensions.cs +++ b/Iceshrimp.Backend/Core/Extensions/QueryableExtensions.cs @@ -10,6 +10,7 @@ namespace Iceshrimp.Backend.Core.Extensions; public static class NoteQueryableExtensions { public static IQueryable WithIncludes(this IQueryable query) { return query.Include(p => p.User) + .ThenInclude(p => p.UserProfile) .Include(p => p.Renote) .ThenInclude(p => p != null ? p.User : null) .Include(p => p.Reply) @@ -34,7 +35,7 @@ public static class NoteQueryableExtensions { .OrderByDescending(note => note.Id), { MinId: not null } => query.Where(note => note.Id.IsGreaterThan(p.MinId)).OrderBy(note => note.Id), { MaxId: not null } => query.Where(note => note.Id.IsLessThan(p.MaxId)).OrderByDescending(note => note.Id), - _ => query + _ => query.OrderByDescending(note => note.Id) }; return query.Take(Math.Min(p.Limit ?? defaultLimit, maxLimit)); @@ -48,13 +49,9 @@ public static class NoteQueryableExtensions { return query.Where(note => note.User == user || note.User.IsFollowedBy(user)); } - public static IQueryable OrderByIdDesc(this IQueryable query) { - return query.OrderByDescending(note => note.Id); - } - public static async Task> RenderAllForMastodonAsync( this IQueryable notes, NoteRenderer renderer) { var list = await notes.ToListAsync(); - return await list.Select(renderer.RenderAsync).AwaitAllAsync(); + return await renderer.RenderManyAsync(list); } } \ No newline at end of file diff --git a/Iceshrimp.Backend/Core/Middleware/AuthenticationMiddleware.cs b/Iceshrimp.Backend/Core/Middleware/AuthenticationMiddleware.cs index 1b35852b..cfc330b6 100644 --- a/Iceshrimp.Backend/Core/Middleware/AuthenticationMiddleware.cs +++ b/Iceshrimp.Backend/Core/Middleware/AuthenticationMiddleware.cs @@ -18,8 +18,12 @@ public class AuthenticationMiddleware(DatabaseContext db) : IMiddleware { return; } - var token = header[7..]; - var session = await db.Sessions.Include(p => p.User).FirstOrDefaultAsync(p => p.Token == token && p.Active); + var token = header[7..]; + var session = await db.Sessions + .Include(p => p.User) + .ThenInclude(p => p.UserProfile) + .FirstOrDefaultAsync(p => p.Token == token && p.Active); + if (session == null) { await next(ctx); return; diff --git a/Iceshrimp.Backend/Core/Middleware/OauthAuthenticationMiddleware.cs b/Iceshrimp.Backend/Core/Middleware/OauthAuthenticationMiddleware.cs index bd81b1c4..8f4107b0 100644 --- a/Iceshrimp.Backend/Core/Middleware/OauthAuthenticationMiddleware.cs +++ b/Iceshrimp.Backend/Core/Middleware/OauthAuthenticationMiddleware.cs @@ -22,6 +22,7 @@ public class OauthAuthenticationMiddleware(DatabaseContext db) : IMiddleware { header = header[7..]; var token = await db.OauthTokens .Include(p => p.User) + .ThenInclude(p => p.UserProfile) .Include(p => p.App) .FirstOrDefaultAsync(p => p.Token == header && p.Active);