diff --git a/.vscode/settings.json b/.vscode/settings.json index 6e22cb5e..16bbe483 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,8 +12,10 @@ "DOTNET", "ecdsa", "envsubst", + "Hsts", "Newtonsoft", "Npgsql", + "PKCE", "postit", "pschneider", "SLNDIR", diff --git a/src/PostIt/PostIt/App.axaml.cs b/src/PostIt/PostIt/App.axaml.cs index ca7e051d..1e0afeaf 100644 --- a/src/PostIt/PostIt/App.axaml.cs +++ b/src/PostIt/PostIt/App.axaml.cs @@ -25,7 +25,7 @@ public partial class App : Application /// DataValidationErrors.SetErrors. /// public IServiceProvider? Services { get; private set; } - + private MainWindow window; public App() { } @@ -137,7 +137,7 @@ public partial class App : Application var homePage = provider.GetRequiredService(); homePage.DataContext = provider.GetRequiredService(); - var window = new MainWindow(); + window = new MainWindow(); window.SessionBanner.DataContext = sessionStatus; // Build the navigation stack from scratch: HomePage is the @@ -165,7 +165,7 @@ public partial class App : Application sessionStatus.LoginSucceeded += () => { var w = (MainWindow)((IClassicDesktopStyleApplicationLifetime)ApplicationLifetime!).MainWindow!; - _ = PushMainPageAsync(provider, w); + _ = PushMainPageAsync(); }; // When the user clicks the "Paramètres" button on the @@ -196,7 +196,7 @@ public partial class App : Application _ = w.NavRoot.PushAsync(settingsPage); }; - window.Opened += async (_, _) => await BootAsync(provider, api, window); + window.Opened += async (_, _) => await BootAsync(provider, api); } else if (ApplicationLifetime is ISingleViewApplicationLifetime singleView) { @@ -223,15 +223,14 @@ public partial class App : Application /// private static async Task BootAsync( IServiceProvider provider, - YavscApiClient api, - MainWindow window) + YavscApiClient api) { var refreshed = await api.TrySilentLoginAsync().ConfigureAwait(true); var sessionStatus = provider.GetRequiredService(); sessionStatus.Refresh(); if (!refreshed) return; - await PushMainPageAsync(provider, window).ConfigureAwait(true); + await PushMainPageAsync().ConfigureAwait(true); } /// @@ -241,12 +240,13 @@ public partial class App : Application /// (interactive login from the banner). Pulled out as a helper so /// the two callers can't drift apart. /// - private static async Task PushMainPageAsync(IServiceProvider provider, MainWindow window) + public static async Task PushMainPageAsync() { - var mainVm = provider.GetRequiredService(); - var mainPage = provider.GetRequiredService(); + var app = (App)Current; + var mainVm = app.Services.GetRequiredService(); + var mainPage = app.Services.GetRequiredService(); mainPage.DataContext = mainVm; - await window.NavRoot.PushAsync(mainPage).ConfigureAwait(true); + await app.window.FindControl("NavRoot").PushAsync(mainPage).ConfigureAwait(true); } private bool TryHandOffCustomSchemeUrl() diff --git a/src/PostIt/PostIt/ViewModels/HomePageViewModel.cs b/src/PostIt/PostIt/ViewModels/HomePageViewModel.cs index 8d5b3a17..c11e396a 100644 --- a/src/PostIt/PostIt/ViewModels/HomePageViewModel.cs +++ b/src/PostIt/PostIt/ViewModels/HomePageViewModel.cs @@ -1,6 +1,7 @@ +using CommunityToolkit.Mvvm.Input; using PostIt; using PostIt.Services; -using PostIt.ViewModels; +namespace PostIt.ViewModels; public class HomePageViewModel : ViewModelBase { @@ -22,7 +23,7 @@ public class HomePageViewModel : ViewModelBase Api = api; Settings = settings; } - + public RelayCommand OpenBlogs { get; set; } = new RelayCommand(() => App.PushMainPageAsync()); /// /// Avalonia designer constructor. Builds a self-contained VM /// with a freshly-constructed Settings so the XAML preview can diff --git a/src/PostIt/PostIt/ViewModels/Settings.cs b/src/PostIt/PostIt/ViewModels/Settings.cs index 5bd3a844..890ca15c 100644 --- a/src/PostIt/PostIt/ViewModels/Settings.cs +++ b/src/PostIt/PostIt/ViewModels/Settings.cs @@ -6,6 +6,7 @@ using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.IO; +using System.Net.Http; using System.Text.Json; using System.Threading; @@ -178,10 +179,20 @@ public partial class Settings : ViewModelBase RedirectUri = Authentication.RedirectUri, Scope = string.Join(' ', MergeScopes(this.Authentication.Scopes)), TokenClientCredentialStyle = IdentityModel.Client.ClientCredentialStyle.PostBody, - PostLogoutRedirectUri = "https//yavsc.pschneider.fr", + PostLogoutRedirectUri = Authentication.Authority, // PKCE is enabled by default when no client_secret is provided. }; + if (IsDevelopmentEnvironment()) + { + // Dev only: allow local/self-signed TLS for discovery/token + // endpoints when the machine does not trust a custom root. + options.BackchannelHandler = new HttpClientHandler + { + ServerCertificateCustomValidationCallback = (_, _, _, _) => true + }; + } + if (browser is not null) options.Browser = browser; @@ -231,6 +242,14 @@ public partial class Settings : ViewModelBase } } + private static bool IsDevelopmentEnvironment() + { + return string.Equals( + Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"), + "Development", + StringComparison.OrdinalIgnoreCase); + } + internal void Load() { if (Loaded) return; diff --git a/src/PostIt/PostIt/Views/HomePage.axaml b/src/PostIt/PostIt/Views/HomePage.axaml index 82473542..7eb6dbb3 100644 --- a/src/PostIt/PostIt/Views/HomePage.axaml +++ b/src/PostIt/PostIt/Views/HomePage.axaml @@ -1,7 +1,12 @@ + + + @@ -9,5 +14,8 @@ FontSize="22" FontWeight="SemiBold" HorizontalAlignment="Center"/> +