-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Sync CRDTs with lexbox during crdt merge (#1206)
* move crdt sync service into LcmCrdt * setup fw-headless to sync crdt changes back to lexbox * close fwdata project once sync is done * defer closing the fw project with a using statement. Make SendReceive async * change sync endpoint to 'api/crdt-sync'
- Loading branch information
Showing
21 changed files
with
272 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
using LcmCrdt; | ||
using LcmCrdt.RemoteSync; | ||
using SIL.Harmony; | ||
|
||
namespace FwHeadless; | ||
|
||
public class CrdtSyncService( | ||
CrdtHttpSyncService httpSyncService, | ||
IHttpClientFactory httpClientFactory, | ||
CurrentProjectService currentProjectService, | ||
DataModel dataModel, | ||
ILogger<CrdtSyncService> logger) | ||
{ | ||
public async Task Sync() | ||
{ | ||
var lexboxRemoteServer = await httpSyncService.CreateProjectSyncable( | ||
currentProjectService.ProjectData, | ||
httpClientFactory.CreateClient(FwHeadlessKernel.LexboxHttpClientName) | ||
); | ||
var syncResults = await dataModel.SyncWith(lexboxRemoteServer); | ||
if (!syncResults.IsSynced) throw new InvalidOperationException("Sync failed"); | ||
logger.LogInformation( | ||
"Synced with Lexbox, Downloaded changes: {MissingFromLocal}, Uploaded changes: {MissingFromRemote}", | ||
syncResults.MissingFromLocal.Length, | ||
syncResults.MissingFromRemote.Length); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
using System.Net; | ||
using LexCore; | ||
using LexCore.Auth; | ||
using Microsoft.Extensions.Caching.Memory; | ||
using Microsoft.Extensions.Options; | ||
|
||
namespace FwHeadless; | ||
|
||
public class HttpClientAuthHandler(IOptions<FwHeadlessConfig> config, IMemoryCache cache, ILogger<HttpClientAuthHandler> logger) : DelegatingHandler | ||
{ | ||
protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) | ||
{ | ||
throw new NotSupportedException("use async apis"); | ||
} | ||
|
||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) | ||
{ | ||
var lexboxUrl = new Uri(config.Value.LexboxUrl); | ||
if (request.RequestUri?.Authority != lexboxUrl.Authority) | ||
{ | ||
return await base.SendAsync(request, cancellationToken); | ||
} | ||
try | ||
{ | ||
await SetAuthHeader(request, cancellationToken, lexboxUrl); | ||
} | ||
catch (Exception e) | ||
{ | ||
throw new InvalidOperationException("Unable to set auth header", e); | ||
} | ||
return await base.SendAsync(request, cancellationToken); | ||
} | ||
|
||
private async Task SetAuthHeader(HttpRequestMessage request, CancellationToken cancellationToken, Uri lexboxUrl) | ||
{ | ||
var cookieContainer = new CookieContainer(); | ||
cookieContainer.Add(new Cookie(LexAuthConstants.AuthCookieName, await GetToken(cancellationToken), null, lexboxUrl.Authority)); | ||
request.Headers.Add("Cookie", cookieContainer.GetCookieHeader(lexboxUrl)); | ||
} | ||
|
||
private async ValueTask<string> GetToken(CancellationToken cancellationToken) | ||
{ | ||
try | ||
{ | ||
return await cache.GetOrCreateAsync("LexboxAuthToken", | ||
async entry => | ||
{ | ||
if (InnerHandler is null) throw new InvalidOperationException("InnerHandler is null"); | ||
logger.LogInformation("Getting auth token"); | ||
var client = new HttpClient(InnerHandler); | ||
client.BaseAddress = new Uri(config.Value.LexboxUrl); | ||
var response = await client.PostAsJsonAsync("/api/login", | ||
new LoginRequest(config.Value.LexboxPassword, config.Value.LexboxUsername), | ||
cancellationToken); | ||
response.EnsureSuccessStatusCode(); | ||
var cookies = response.Headers.GetValues("Set-Cookie"); | ||
var cookieContainer = new CookieContainer(); | ||
cookieContainer.SetCookies(response.RequestMessage!.RequestUri!, cookies.Single()); | ||
var authCookie = cookieContainer.GetAllCookies() | ||
.FirstOrDefault(c => c.Name == LexAuthConstants.AuthCookieName); | ||
if (authCookie is null) throw new InvalidOperationException("Auth cookie not found"); | ||
entry.SetValue(authCookie.Value); | ||
entry.AbsoluteExpiration = authCookie.Expires; | ||
logger.LogInformation("Got auth token: {AuthToken}", authCookie.Value); | ||
return authCookie.Value; | ||
}) ?? throw new NullReferenceException("unable to get the login token"); | ||
} | ||
catch (Exception e) | ||
{ | ||
throw new InvalidOperationException("Unable to get auth token", e); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.