Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "9.0.0",
"version": "9.0.4",
"commands": [
"dotnet-ef"
],
Expand Down
5 changes: 0 additions & 5 deletions Tiltfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@ cfg = config.parse()
forward_lexbox = not cfg.get("lexbox-api-local", False)
prod_ui_build = cfg.get("prod-ui-build", False)

docker_build(
'local-dev-init',
'data'
)

docker_build(
'ghcr.io/sillsdev/lexbox-api',
context='backend',
Expand Down
57 changes: 28 additions & 29 deletions backend/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,11 @@
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
<PackageVersion Include="CrystalQuartz.AspNetCore" Version="7.2.0-beta" />
<PackageVersion Include="DataAnnotatedModelValidations" Version="6.0.0" />
<PackageVersion Include="EntityFrameworkCore.Projectables" Version="3.0.4" />
<PackageVersion Include="EntityFrameworkCore.Projectables.Abstractions" Version="4.0.0-preview.4" />
<PackageVersion Include="FluentAssertions" Version="7.0.0-alpha.5" />
<PackageVersion Include="FluentValidation" Version="11.11.0" />
<PackageVersion Include="GitHubActionsTestLogger" Version="2.4.1" />
<PackageVersion Include="Gridify" Version="2.16.2" />
<PackageVersion Include="Gridify.EntityFramework" Version="2.15.0" />
<PackageVersion Include="Gridify" Version="2.16.3" />
<PackageVersion Include="Gridify.EntityFramework" Version="2.16.3" />
<PackageVersion Include="HotChocolate.Analyzers" Version="13.9.14" />
<PackageVersion Include="HotChocolate.AspNetCore" Version="14.0.0" />
<PackageVersion Include="HotChocolate.AspNetCore.Authorization" Version="14.0.0" />
Expand All @@ -27,7 +25,7 @@
<PackageVersion Include="Humanizer.Core" Version="2.14.1" />
<PackageVersion Include="icu.net" Version="3.0.1" />
<PackageVersion Include="linq2db.AspNet" Version="5.4.1" />
<PackageVersion Include="linq2db.EntityFrameworkCore" Version="8.1.0" />
<PackageVersion Include="linq2db.EntityFrameworkCore" Version="9.1.0-preview.4" />
<PackageVersion Include="MailKit" Version="4.7.1.1" />
<PackageVersion Include="Meziantou.Extensions.Logging.Xunit" Version="1.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Google" Version="8.0.10" />
Expand All @@ -36,25 +34,26 @@
<PackageVersion Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="$(MauiVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.15" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.15" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Caching.Hybrid" Version="9.0.0-preview.9.24556.5" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="9.0.2" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.2" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.2" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.2" />
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="8.0.15" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Embedded" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.2" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Embedded" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="9.2.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.2" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="9.0.2" />
<PackageVersion Include="Microsoft.Extensions.Logging.Debug" Version="9.0.2" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.2" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.2" />
<PackageVersion Include="Microsoft.Extensions.Options.DataAnnotations" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Logging.Debug" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Options.DataAnnotations" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.ServiceDiscovery" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.TimeProvider.Testing" Version="9.0.0" />
<PackageVersion Include="Microsoft.ICU.ICU4C.Runtime" Version="72.1.0.3" />
Expand All @@ -70,9 +69,9 @@
<PackageVersion Include="Moq" Version="4.20.70" />
<PackageVersion Include="Moq.Contrib.HttpClient" Version="1.4.0" />
<PackageVersion Include="Nito.AsyncEx.Coordination" Version="5.1.2" />
<PackageVersion Include="Npgsql" Version="8.0.6" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.11" />
<PackageVersion Include="Npgsql.OpenTelemetry" Version="8.0.6" />
<PackageVersion Include="Npgsql" Version="9.0.3" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<PackageVersion Include="Npgsql.OpenTelemetry" Version="9.0.3" />
<PackageVersion Include="NReco.Logging.File" Version="1.2.1" />
<PackageVersion Include="OpenIddict.AspNetCore" Version="5.8.0" />
<PackageVersion Include="OpenIddict.EntityFrameworkCore" Version="5.8.0" />
Expand Down Expand Up @@ -113,9 +112,9 @@
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.2.0" />
<PackageVersion Include="System.Linq.Async" Version="6.0.1" />
<PackageVersion Include="System.Reactive" Version="6.0.1" />
<PackageVersion Include="System.Security.Cryptography.Xml" Version="9.0.0" />
<PackageVersion Include="System.Text.Encodings.Web" Version="9.0.0" />
<PackageVersion Include="System.Text.Json" Version="9.0.0" />
<PackageVersion Include="System.Security.Cryptography.Xml" Version="9.0.4" />
<PackageVersion Include="System.Text.Encodings.Web" Version="9.0.4" />
<PackageVersion Include="System.Text.Json" Version="9.0.4" />
<PackageVersion Include="SystemTextJson.JsonDiffPatch" Version="2.0.0" />
<PackageVersion Include="SystemTextJsonPatch" Version="3.2.1" />
<PackageVersion Include="tusdotnet" Version="2.8.0" />
Expand All @@ -130,4 +129,4 @@
<ItemGroup>
<GlobalPackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.11.20" />
</ItemGroup>
</Project>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -375,4 +375,4 @@
Relational:ViewName:
Relational:ViewSchema:
Annotations:
ProductVersion: 8.0.15
ProductVersion: 9.0.4
1 change: 1 addition & 0 deletions backend/FwLite/LcmCrdt/LcmCrdt.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" />
<PackageReference Include="Refit" />
Expand Down
14 changes: 4 additions & 10 deletions backend/LexBoxApi/Controllers/LegacyProjectApiController.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.ComponentModel.DataAnnotations;
using System.Net.Mime;
using EntityFrameworkCore.Projectables;
using LexCore;
using LexCore.Entities;
using LexCore.ServiceInterfaces;
Expand Down Expand Up @@ -57,7 +56,10 @@ public async Task<ActionResult<LegacyApiProject[]>> Projects(string userName, Pr
member.Project.Name,
//it seems this is largely ignored by the client as it uses the LF domain instead
"http://public.languagedepot.org",
RoleToString(member.Role)))
//instead of using toString which could change if we rename the enum, we only ever want to return these 3 values.
member.Role == ProjectRole.Manager ? "manager"
: member.Role == ProjectRole.Editor ? "editor"
: "unknown"))//fieldworks doesn't know about or support observers
})
.FirstOrDefaultAsync();
if (user == null)
Expand All @@ -73,14 +75,6 @@ public async Task<ActionResult<LegacyApiProject[]>> Projects(string userName, Pr

return user.projects.ToArray();
}

[Projectable]
private string RoleToString(ProjectRole role) =>
//instead of using toString which could change if we rename the enum, we only ever want to return these 3 values.
//this needs to be ugly so that projectable will work :(
role == ProjectRole.Manager ? "manager"
: role == ProjectRole.Editor ? "editor"
: "unknown";//fieldworks doesn't know about or support observers
}

public record LegacyApiProject(string Identifier, string Name, string Repository, string Role);
Expand Down
31 changes: 0 additions & 31 deletions backend/LexBoxApi/GraphQL/EfCoreProjectablesFieldHandler.cs

This file was deleted.

33 changes: 17 additions & 16 deletions backend/LexBoxApi/GraphQL/LexQueries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using LexCore.Entities;
using LexCore.ServiceInterfaces;
using LexData;
using LinqToDB.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

namespace LexBoxApi.GraphQL;
Expand All @@ -24,8 +25,7 @@ public async Task<IQueryable<Project>> MyProjects(
IResolverContext context)
{
var userId = loggedInContext.User.Id;
var myProjects = await projectService.UserProjects(userId)
.AsNoTracking().Project(context).ToListAsync();
var myProjects = await projectService.UserProjects(userId).Project(context).ToListAsyncLinqToDB();

if (loggedInContext.User.IsOutOfSyncWithMyProjects(myProjects))
{
Expand All @@ -43,11 +43,11 @@ public IQueryable<Project> Projects(LexBoxDbContext context, bool withDeleted =
{
if (withDeleted)
{
return context.Projects.AsNoTracking().IgnoreQueryFilters();
return context.Projects.ToLinqToDB().IgnoreQueryFilters();
}
else
{
return context.Projects.AsNoTracking();
return context.Projects.ToLinqToDB();
}
}

Expand All @@ -56,7 +56,7 @@ public IQueryable<Project> Projects(LexBoxDbContext context, bool withDeleted =
public IQueryable<DraftProject> MyDraftProjects(LoggedInContext loggedInContext, LexBoxDbContext context)
{
var userId = loggedInContext.User.Id;
return context.DraftProjects.AsNoTracking().Where(p => p.ProjectManagerId == userId);
return context.DraftProjects.ToLinqToDB().Where(p => p.ProjectManagerId == userId);
}

[UseProjection]
Expand All @@ -65,7 +65,7 @@ public IQueryable<DraftProject> MyDraftProjects(LoggedInContext loggedInContext,
[AdminRequired]
public IQueryable<DraftProject> DraftProjects(LexBoxDbContext context)
{
return context.DraftProjects.AsNoTracking();
return context.DraftProjects.ToLinqToDB();
}

public record ProjectsByLangCodeAndOrgInput(Guid OrgId, string LangCode);
Expand All @@ -76,7 +76,7 @@ public IQueryable<Project> ProjectsByLangCodeAndOrg(LoggedInContext loggedInCont
if (!loggedInContext.User.IsAdmin && !permissionService.IsOrgMember(input.OrgId)) throw new UnauthorizedAccessException();
// Convert 3-letter code to 2-letter code if relevant, otherwise leave as-is
var langCode = LangTagConstants.ThreeToTwo.GetValueOrDefault(input.LangCode, input.LangCode);
var query = context.Projects.AsNoTracking().Where(p =>
var query = context.Projects.ToLinqToDB().Where(p =>
p.Organizations.Any(o => o.Id == input.OrgId) &&
p.FlexProjectMetadata != null &&
p.FlexProjectMetadata.WritingSystems != null &&
Expand All @@ -103,7 +103,7 @@ public record ProjectsInMyOrgInput(Guid OrgId);
public IQueryable<Project> ProjectsInMyOrg(LoggedInContext loggedInContext, LexBoxDbContext context, IPermissionService permissionService, ProjectsInMyOrgInput input)
{
if (!loggedInContext.User.IsAdmin && !permissionService.IsOrgMember(input.OrgId)) throw new UnauthorizedAccessException();
var query = context.Projects.AsNoTracking().Where(p => p.Organizations.Any(o => o.Id == input.OrgId));
var query = context.Projects.ToLinqToDB().Where(p => p.Organizations.Any(o => o.Id == input.OrgId));
// Org admins can see all projects, everyone else can only see non-confidential
if (!permissionService.CanEditOrg(input.OrgId))
{
Expand All @@ -117,7 +117,7 @@ public IQueryable<Project> ProjectsInMyOrg(LoggedInContext loggedInContext, LexB
public async Task<IQueryable<Project>> ProjectById(LexBoxDbContext context, IPermissionService permissionService, Guid projectId)
{
await permissionService.AssertCanViewProject(projectId);
return context.Projects.AsNoTracking().Where(p => p.Id == projectId);
return context.Projects.ToLinqToDB().Where(p => p.Id == projectId);
}

public record ProjectStatus(Guid Id, bool Exists, bool Deleted, string? AccessibleCode);
Expand All @@ -127,7 +127,7 @@ public async Task<ProjectStatus> GetProjectStatus(LexBoxDbContext context, IPerm
{
var project = await context.Projects.Include(p => p.Users)
.AsNoTracking().IgnoreQueryFilters()
.SingleOrDefaultAsync(p => p.Id == projectId);
.SingleOrDefaultAsyncLinqToDB(p => p.Id == projectId);

if (project is null) return new ProjectStatus(projectId, false, false, null);
if (project.DeletedDate != null) return new ProjectStatus(projectId, true, true, null);
Expand All @@ -150,7 +150,7 @@ public async Task<ProjectStatus> GetProjectStatus(LexBoxDbContext context, IPerm
IResolverContext context,
string code)
{
var project = await dbContext.Projects.Where(p => p.Code == code).AsNoTracking().Project(context).SingleOrDefaultAsync();
var project = await dbContext.Projects.Where(p => p.Code == code).Project(context).SingleOrDefaultAsyncLinqToDB();

if (project is null) return project;

Expand All @@ -167,7 +167,7 @@ public async Task<ProjectStatus> GetProjectStatus(LexBoxDbContext context, IPerm
[UseSorting]
public IQueryable<Organization> Orgs(LexBoxDbContext context)
{
return context.Orgs.AsNoTracking();
return context.Orgs.ToLinqToDB();
}

[UseProjection]
Expand All @@ -181,7 +181,7 @@ public async Task<IQueryable<Organization>> MyOrgs(
{
var userId = loggedInContext.User.Id;
var myOrgs = await dbContext.Orgs.Where(o => o.Members.Any(m => m.UserId == userId))
.AsNoTracking().Project(context).ToListAsync();
.ToLinqToDB().Project(context).ToListAsyncLinqToDB();

if (loggedInContext.User.IsOutOfSyncWithMyOrgs(myOrgs))
{
Expand Down Expand Up @@ -223,7 +223,8 @@ public IQueryable<User> UsersICanSee(UserService userService, LoggedInContext lo
var projectContext =
context.GetLocalStateOrDefault<IResolverContext>("HotChocolate.Data.Projections.ProxyContext") ??
context;
var org = await dbContext.Orgs.Where(o => o.Id == orgId).AsNoTracking().Project(projectContext).SingleOrDefaultAsync();
var org = await dbContext.Orgs.Where(o => o.Id == orgId).Project(projectContext)
.SingleOrDefaultAsyncLinqToDB();
if (org is null) return org;

var updatedUser = loggedInContext.User.IsOutOfSyncWithOrg(org)
Expand Down Expand Up @@ -259,7 +260,7 @@ public IQueryable<User> UsersICanSee(UserService userService, LoggedInContext lo
public IQueryable<User> Users(LexBoxDbContext context)
{
//default order by, can be overwritten by the gql query
return context.Users.OrderBy(u => u.Name);
return context.Users.ToLinqToDB().OrderBy(u => u.Name);
}

public async Task<MeDto?> Me(LexBoxDbContext context, LoggedInContext loggedInContext)
Expand All @@ -281,7 +282,7 @@ public IQueryable<User> Users(LexBoxDbContext context)
// Only site admins and org admins are allowed to run this query
if (!permissionService.CanEditOrg(orgId)) return null;

var user = await context.Users.AsNoTracking().Include(u => u.Organizations).Include(u => u.CreatedBy).Where(u => u.Id == userId).FirstOrDefaultAsync();
var user = await context.Users.Include(u => u.Organizations).Include(u => u.CreatedBy).Where(u => u.Id == userId).FirstOrDefaultAsyncLinqToDB();
if (user is null) return null;

var userInOrg = user.Organizations.Any(om => om.OrgId == orgId);
Expand Down
1 change: 0 additions & 1 deletion backend/LexBoxApi/LexBoxApi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
<GarbageCollectionAdaptationMode>1</GarbageCollectionAdaptationMode>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AppAny.Quartz.EntityFrameworkCore.Migrations.PostgreSQL" />
<PackageReference Include="CrystalQuartz.AspNetCore" />
<PackageReference Include="DataAnnotatedModelValidations" />
<PackageReference Include="HotChocolate.Analyzers" />
Expand Down
4 changes: 0 additions & 4 deletions backend/LexBoxApi/ScheduledTasksKernel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ public static class ScheduledTasksKernel
{
public static void AddScheduledTasks(this IServiceCollection services, IConfiguration configuration)
{
services.ConfigureDbModel(builder =>
{
builder.AddQuartz(b => b.UsePostgreSql());
});
services.AddQuartz(q =>
{
q.UsePersistentStore(options =>
Expand Down
Loading
Loading