Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into chore/call-fw-head…
Browse files Browse the repository at this point in the history
…less-sync-from-lexbox
  • Loading branch information
myieye committed Nov 22, 2024
2 parents 2d63651 + 0da7cf8 commit 4862c48
Show file tree
Hide file tree
Showing 63 changed files with 489 additions and 331 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/develop-ui.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@ jobs:
cache-dependency-path: './frontend/pnpm-lock.yaml'
- run: pnpm install
- run: pnpm run -r build # We need code/types generated by the build (e.g. gql/generated)
- run: pnpm run -r check --output machine
- run: pnpm run -r lint:report
- id: svelte_check
run: pnpm run -r --no-bail check --output machine
- run: pnpm run -r --no-bail lint:report
if: ${{ always() && steps.svelte_check.outcome != 'cancelled' }}
- name: Annotate Code Linting REsults
uses: ataylorme/eslint-annotate-action@d57a1193d4c59cbfbf3f86c271f42612f9dbd9e9 # v3.0.0
if: always()
Expand Down
32 changes: 27 additions & 5 deletions backend/FwLite/FwLiteDesktop/FwLiteDesktopKernel.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using FwLiteDesktop.ServerBridge;
using Windows.ApplicationModel;
using FwLiteDesktop.ServerBridge;
using LcmCrdt;
using LocalWebApp.Auth;
using Microsoft.Extensions.Configuration;
Expand All @@ -15,21 +16,25 @@ public static void AddFwLiteDesktopServices(this IServiceCollection services,
ILoggingBuilder logging)
{
services.AddSingleton<MainPage>();
configuration.AddJsonFile("appsettings.json", optional: true);

string environment = "Production";
#if DEBUG
environment = "Development";
#endif
var defaultDataPath = IsPackagedApp ? FileSystem.AppDataDirectory : Directory.GetCurrentDirectory();
var baseDataPath = Path.GetFullPath(configuration.GetSection("FwLiteDesktop").GetValue<string>("BaseDataDir") ?? defaultDataPath);
Directory.CreateDirectory(baseDataPath);
var serverManager = new ServerManager(environment, webAppBuilder =>
{
webAppBuilder.Logging.AddFile(Path.Combine(FileSystem.AppDataDirectory, "web-app.log"));
webAppBuilder.Logging.AddFile(Path.Combine(baseDataPath, "web-app.log"));
webAppBuilder.Services.Configure<LcmCrdtConfig>(config =>
{
config.ProjectPath = FileSystem.AppDataDirectory;
config.ProjectPath = baseDataPath;
});
webAppBuilder.Services.Configure<AuthConfig>(config =>
{
config.CacheFileName = Path.Combine(FileSystem.AppDataDirectory, "msal.cache");
config.CacheFileName = Path.Combine(baseDataPath, "msal.cache");
config.SystemWebViewLogin = true;
});
});
Expand All @@ -39,10 +44,27 @@ public static void AddFwLiteDesktopServices(this IServiceCollection services,
services.AddSingleton<IHostEnvironment>(_ => _.GetRequiredService<ServerManager>().WebServices.GetRequiredService<IHostEnvironment>());
configuration.Add<ServerConfigSource>(source => source.ServerManager = serverManager);
services.AddOptions<LocalWebAppConfig>().BindConfiguration("LocalWebApp");
logging.AddFile(Path.Combine(FileSystem.AppDataDirectory, "app.log"));
logging.AddFile(Path.Combine(baseDataPath, "app.log"));
logging.AddConsole();
#if DEBUG
logging.AddDebug();
#endif
}

static readonly Lazy<bool> IsPackagedAppLazy = new(static () =>
{
try
{
if (Package.Current != null)
return true;
}
catch
{
// no-op
}

return false;
});

public static bool IsPackagedApp => IsPackagedAppLazy.Value;
}
1 change: 0 additions & 1 deletion backend/FwLite/FwLiteDesktop/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ public static MauiApp CreateMauiApp()
});
}));

Directory.CreateDirectory(FileSystem.AppDataDirectory);
builder.Services.AddFwLiteDesktopServices(builder.Configuration, builder.Logging);

holder.App = builder.Build();
Expand Down
6 changes: 3 additions & 3 deletions backend/FwLite/FwLiteProjectSync.Tests/EntrySyncTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace FwLiteProjectSync.Tests;

public class EntrySyncTests : IClassFixture<SyncFixture>
{
private readonly AutoFaker _autoFaker = new(builder => builder.WithOverride(new MultiStringOverride()).WithOverride(new ObjectWithIdOverride()));
private static readonly AutoFaker AutoFaker = new(builder => builder.WithOverride(new MultiStringOverride()).WithOverride(new ObjectWithIdOverride()));
public EntrySyncTests(SyncFixture fixture)
{
_fixture = fixture;
Expand All @@ -20,8 +20,8 @@ public EntrySyncTests(SyncFixture fixture)
[Fact]
public async Task CanSyncRandomEntries()
{
var createdEntry = await _fixture.CrdtApi.CreateEntry(await _autoFaker.EntryReadyForCreation(_fixture.CrdtApi));
var after = await _autoFaker.EntryReadyForCreation(_fixture.CrdtApi, entryId: createdEntry.Id);
var createdEntry = await _fixture.CrdtApi.CreateEntry(await AutoFaker.EntryReadyForCreation(_fixture.CrdtApi));
var after = await AutoFaker.EntryReadyForCreation(_fixture.CrdtApi, entryId: createdEntry.Id);
await EntrySync.Sync(after, createdEntry, _fixture.CrdtApi);
var actual = await _fixture.CrdtApi.GetEntry(after.Id);
actual.Should().NotBeNull();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.1"/>
<PackageReference Include="FluentAssertions" Version="6.12.0"/>
<PackageReference Include="Soenneker.Utils.AutoBogus" Version="2.1.278" />
<PackageReference Include="Soenneker.Utils.AutoBogus" Version="3.0.410" />
<PackageReference Include="xunit" Version="2.9.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<PrivateAssets>all</PrivateAssets>
Expand Down
8 changes: 4 additions & 4 deletions backend/FwLite/FwLiteProjectSync.Tests/UpdateDiffTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace FwLiteProjectSync.Tests;

public class UpdateDiffTests
{
private readonly AutoFaker _autoFaker = new(new AutoFakerConfig()
private static readonly AutoFaker AutoFaker = new(new AutoFakerConfig()
{
Overrides = [new MultiStringOverride(), new WritingSystemIdOverride()]
});
Expand All @@ -18,7 +18,7 @@ public class UpdateDiffTests
public void EntryDiffShouldUpdateAllFields()
{
var before = new Entry();
var after = _autoFaker.Generate<Entry>();
var after = AutoFaker.Generate<Entry>();
var entryDiffToUpdate = EntrySync.EntryDiffToUpdate(before, after);
ArgumentNullException.ThrowIfNull(entryDiffToUpdate);
entryDiffToUpdate.Apply(before);
Expand All @@ -33,7 +33,7 @@ public void EntryDiffShouldUpdateAllFields()
public async Task SenseDiffShouldUpdateAllFields()
{
var before = new Sense();
var after = _autoFaker.Generate<Sense>();
var after = AutoFaker.Generate<Sense>();
var senseDiffToUpdate = await SenseSync.SenseDiffToUpdate(before, after);
ArgumentNullException.ThrowIfNull(senseDiffToUpdate);
senseDiffToUpdate.Apply(before);
Expand All @@ -44,7 +44,7 @@ public async Task SenseDiffShouldUpdateAllFields()
public void ExampleSentenceDiffShouldUpdateAllFields()
{
var before = new ExampleSentence();
var after = _autoFaker.Generate<ExampleSentence>();
var after = AutoFaker.Generate<ExampleSentence>();
var exampleSentenceDiffToUpdate = ExampleSentenceSync.DiffToUpdate(before, after);
ArgumentNullException.ThrowIfNull(exampleSentenceDiffToUpdate);
exampleSentenceDiffToUpdate.Apply(before);
Expand Down
4 changes: 2 additions & 2 deletions backend/FwLite/LcmCrdt.Tests/DataModelSnapshotTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace LcmCrdt.Tests;

public class DataModelSnapshotTests : IAsyncLifetime
{
private static AutoFaker _faker = new AutoFaker(new AutoFakerConfig()
private static readonly AutoFaker Faker = new AutoFaker(new AutoFakerConfig()
{
Overrides = [new MultiStringOverride(), new WritingSystemIdOverride()]
});
Expand Down Expand Up @@ -90,7 +90,7 @@ public void VerifyIObjectWithIdsMatchAdapterGetObjectTypeName()
foreach (var jsonDerivedType in types)
{
var typeDiscriminator = jsonDerivedType.TypeDiscriminator.Should().BeOfType<string>().Subject;
var obj = _faker.Generate(jsonDerivedType.DerivedType);
var obj = Faker.Generate(jsonDerivedType.DerivedType);
new MiniLcmCrdtAdapter((IObjectWithId)obj).GetObjectTypeName().Should().Be(typeDiscriminator);
}
}
Expand Down
4 changes: 2 additions & 2 deletions backend/FwLite/LcmCrdt.Tests/EntityCopyMethodTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace LcmCrdt.Tests;

public class EntityCopyMethodTests
{
private readonly AutoFaker _autoFaker = new(new AutoFakerConfig()
private static readonly AutoFaker AutoFaker = new(new AutoFakerConfig()
{
Overrides = [new MultiStringOverride(), new WritingSystemIdOverride()]
});
Expand All @@ -35,7 +35,7 @@ public static IEnumerable<object[]> GetEntityTypes()
public void EntityCopyMethodShouldCopyAllFields(Type type)
{
type.IsAssignableTo(typeof(IObjectWithId)).Should().BeTrue();
var entity = (IObjectWithId) _autoFaker.Generate(type);
var entity = (IObjectWithId) AutoFaker.Generate(type);
var copy = entity.Copy();
copy.Should().BeEquivalentTo(entity, options => options.IncludingAllRuntimeProperties());
}
Expand Down
2 changes: 1 addition & 1 deletion backend/FwLite/LcmCrdt.Tests/LcmCrdt.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.0" />
<PackageReference Include="FluentAssertions" Version="6.12.0"/>
<PackageReference Include="Soenneker.Utils.AutoBogus" Version="2.1.278" />
<PackageReference Include="Soenneker.Utils.AutoBogus" Version="3.0.410" />
<PackageReference Include="Verify.Xunit" Version="27.0.1" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
Expand Down
4 changes: 2 additions & 2 deletions backend/FwLite/LcmCrdt/CurrentProjectService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public async ValueTask<ProjectData> GetProjectData()

private static string CacheKey(CrdtProject project)
{
return project.DbPath + "|ProjectData";
return project.Name + "|ProjectData";
}

private static string CacheKey(Guid projectId)
Expand Down Expand Up @@ -57,7 +57,7 @@ private void RemoveProjectDataCache()
memoryCache.Remove(CacheKey(Project));
}

public async Task SetProjectSyncOrigin(Uri domain, Guid? id)
public async Task SetProjectSyncOrigin(Uri? domain, Guid? id)
{
var originDomain = ProjectData.GetOriginDomain(domain);
if (id is null)
Expand Down
8 changes: 8 additions & 0 deletions backend/FwLite/LocalWebApp/Auth/AuthConfig.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations;
using LcmCrdt;

namespace LocalWebApp.Auth;

Expand All @@ -15,6 +16,13 @@ public LexboxServer GetServerByAuthority(string authority)
{
return LexboxServers.FirstOrDefault(s => s.Authority.Authority == authority) ?? throw new ArgumentException($"Server {authority} not found");
}

public LexboxServer GetServer(ProjectData projectData)
{
var originDomain = projectData.OriginDomain;
if (string.IsNullOrEmpty(originDomain)) throw new InvalidOperationException("No origin domain in project data");
return GetServerByAuthority(new Uri(originDomain).Authority);
}
public LexboxServer GetServer(string serverName)
{
return LexboxServers.FirstOrDefault(s => s.DisplayName == serverName) ?? throw new ArgumentException($"Server {serverName} not found");
Expand Down
25 changes: 18 additions & 7 deletions backend/FwLite/LocalWebApp/Auth/AuthHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Net.Http.Headers;
using System.Security.Cryptography;
using LocalWebApp.Routes;
using LocalWebApp.Services;
using Microsoft.Extensions.Options;
using Microsoft.Identity.Client;
using Microsoft.Identity.Client.Extensions.Msal;
Expand All @@ -21,7 +22,8 @@ public class AuthHelpers
private readonly IHttpMessageHandlerFactory _httpMessageHandlerFactory;
private readonly OAuthService _oAuthService;
private readonly UrlContext _urlContext;
private readonly Uri _authority;
private readonly LexboxServer _lexboxServer;
private readonly LexboxProjectService _lexboxProjectService;
private readonly ILogger<AuthHelpers> _logger;
private readonly IPublicClientApplication _application;
AuthenticationResult? _authResult;
Expand All @@ -32,14 +34,16 @@ public AuthHelpers(LoggerAdapter loggerAdapter,
LinkGenerator linkGenerator,
OAuthService oAuthService,
UrlContext urlContext,
Uri authority,
LexboxServer lexboxServer,
LexboxProjectService lexboxProjectService,
ILogger<AuthHelpers> logger,
IHostEnvironment hostEnvironment)
{
_httpMessageHandlerFactory = httpMessageHandlerFactory;
_oAuthService = oAuthService;
_urlContext = urlContext;
_authority = authority;
_lexboxServer = lexboxServer;
_lexboxProjectService = lexboxProjectService;
_logger = logger;
(var hostUrl, _isRedirectHostGuess) = urlContext.GetUrl();
_redirectHost = HostString.FromUriComponent(hostUrl);
Expand All @@ -56,7 +60,7 @@ public AuthHelpers(LoggerAdapter loggerAdapter,
.WithLogging(loggerAdapter, hostEnvironment.IsDevelopment())
.WithHttpClientFactory(new HttpClientFactoryAdapter(httpMessageHandlerFactory))
.WithRedirectUri(redirectUri)
.WithOidcAuthority(authority.ToString())
.WithOidcAuthority(lexboxServer.Authority.ToString())
.Build();
_ = MsalCacheHelper.CreateAsync(BuildCacheProperties(options.Value.CacheFileName)).ContinueWith(
task =>
Expand Down Expand Up @@ -109,9 +113,10 @@ public HttpClient GetHttpClient()
}
}

public async Task<OAuthService.SignInResult> SignIn(CancellationToken cancellation = default)
public async Task<OAuthService.SignInResult> SignIn(string returnUrl, CancellationToken cancellation = default)
{
return await _oAuthService.SubmitLoginRequest(_application, cancellation);
InvalidateProjectCache();
return await _oAuthService.SubmitLoginRequest(_application, returnUrl, cancellation);
}

public async Task Logout()
Expand All @@ -122,6 +127,12 @@ public async Task Logout()
{
await _application.RemoveAsync(account);
}
InvalidateProjectCache();
}

private void InvalidateProjectCache()
{
_lexboxProjectService.InvalidateProjectsCache(_lexboxServer);
}

private async ValueTask<AuthenticationResult?> GetAuth()
Expand Down Expand Up @@ -177,7 +188,7 @@ await _application

var handler = _httpMessageHandlerFactory.CreateHandler(AuthHttpClientName);
var client = new HttpClient(handler, false);
client.BaseAddress = _authority;
client.BaseAddress = _lexboxServer.Authority;
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", auth.AccessToken);
return client;
}
Expand Down
28 changes: 12 additions & 16 deletions backend/FwLite/LocalWebApp/Auth/AuthHelpersFactory.cs
Original file line number Diff line number Diff line change
@@ -1,33 +1,34 @@
using System.Collections.Concurrent;
using LcmCrdt;
using LocalWebApp.Services;
using Microsoft.Extensions.Options;

namespace LocalWebApp.Auth;

public class AuthHelpersFactory(
IServiceProvider provider,
ProjectContext projectContext,
IOptions<AuthConfig> options,
IHttpContextAccessor contextAccessor)
{
private readonly ConcurrentDictionary<string, AuthHelpers> _helpers = new();

private string AuthorityKey(Uri authority) =>
authority.GetComponents(UriComponents.HostAndPort, UriFormat.Unescaped);
private string AuthorityKey(LexboxServer server) => "AuthHelper|" + server.Authority.Authority;

/// <summary>
/// gets an Auth Helper for the given authority
/// gets an Auth Helper for the given server
/// </summary>
/// <param name="authority">should include scheme, host and port, no path</param>
public AuthHelpers GetHelper(Uri authority)
public AuthHelpers GetHelper(LexboxServer server)
{
var helper = _helpers.GetOrAdd(AuthorityKey(authority),
static (host, arg) => ActivatorUtilities.CreateInstance<AuthHelpers>(arg.provider, arg.authority),
(authority, provider));
var helper = _helpers.GetOrAdd(AuthorityKey(server),
static (host, arg) => ActivatorUtilities.CreateInstance<AuthHelpers>(arg.provider, arg.server),
(server, provider));
//an auth helper can get created based on the server host, however in development that will not be the same as the client host
//so we need to recreate it if the host is not valid
if (!helper.IsHostUrlValid())
{
_helpers.TryRemove(AuthorityKey(authority), out _);
return GetHelper(authority);
_helpers.TryRemove(AuthorityKey(server), out _);
return GetHelper(server);
}

return helper;
Expand All @@ -40,12 +41,7 @@ public AuthHelpers GetHelper(ProjectData project)
{
var originDomain = project.OriginDomain;
if (string.IsNullOrEmpty(originDomain)) throw new InvalidOperationException("No origin domain in project data");
return GetHelper(new Uri(originDomain));
}

public AuthHelpers GetHelper(LexboxServer server)
{
return GetHelper(server.Authority);
return GetHelper(options.Value.GetServer(project));
}

/// <summary>
Expand Down
Loading

0 comments on commit 4862c48

Please sign in to comment.