Apply PageHelpers.ActivePage to all 13 <a class="dropdown-item">
entries across the Plateforme, Administration, and account
dropdown menus so users see which section they're in. The
Logout entry matches Account/Logout specifically to avoid
colliding with the Register/Signin entries on the same Account
controller.
Add PageHelpers.ActivePage extension and apply it to top-level nav
items and the Account/Register + Account/Signin items in _LoginPartial,
so the current route gets the active class and aria-current="page"
for accessibility.
The previous commit's table incorrectly stated that
appsettings-org.Development.json is committed; it is in fact
matched by .gitignore (appsettings-*.*.json), so each developer
generates their own from the template documented here. Fix the
table and clarify the role.
The localhoist typo that lived in the previously-shown blob is
not versioned, so it does not propagate via git.
The Yavsc.Org service reads appsettings-org.json at runtime, but the
contrib/Makefile renames that file to appsettings-org-dist.json right
before deploying to $(BASEAPPDIR), so first-time operators have to
copy the dist variant back to appsettings-org.json on the server and
fill in their actual values. None of that was documented; this commit
adds a Fichiers de configuration d'Yavsc.Org section under Paramétrage.
The section also notes that Site.ExternalUrl is now consumed by the
IdentityServer EF seed (added in the previous PostIt PKCE commit) to
authorize a RedirectUri for the 'postit' OIDC client, so PostIt can
be embedded in a Yavsc.Org web page without redirect_uri mismatch.
Side note: the appsettings-org.Development.json template points at
'https://localhoist:5001' which looks like a typo for 'localhost'.
Flagged in the README so it doesn't get copy-pasted into a new
environment as-is.
The previous commit set Platform.CreateBrowser to null on the desktop
side, so LoginAsync would still fail with 'No browser is available'.
Close that loop with an explicit desktop bootstrap.
PostIt.Desktop/PlatformBootstrap.cs mirrors the Android side: it
populates Platform.DefaultRedirectUri and Platform.CreateBrowser
once at startup. Program.Main calls EnsureInitialized before
BuildAvaloniaApp so the LoginPageViewModel sees a working browser
before any login attempt.
The Yavsc.Org seed now reads Site:ExternalUrl from configuration so
the RedirectUri list for the PostIt client follows the same setting
as the rest of the application (same value used in
Administration/ClientController, AccountController, etc.). Without
this, an embedded 'launch PostIt from a Yavsc.Org page' scenario
would be rejected by IdentityServer (redirect_uri mismatch).
BuildPostItRedirectUris is a small helper that yields the constant
PostItRedirectUris (loopback + Android custom scheme) followed by
Site:ExternalUrl when set. Both SeedNewPostItClient (fresh db) and
MigratePostItClientToPublic (existing db) consume it. The legacy
cleanup block (which used to remove https://yavsc.pschneider.fr/
and yavsc://callback) is dropped: Site:ExternalUrl is now the
canonical way to authorise that path and may legitimately equal
that value.
The earlier commit removed the client_secret and wired
MainActivity.OnNewIntent to AndroidOidcCallbackSink, but
IdentityModel.OidcClient.LoginAsync still had no IBrowser to drive
the user-agent half of the flow. Without it, the desktop / browser
projects continue to fail at login with 'No browser is available'.
Android now plugs in Chrome Custom Tabs:
* PostIt.Android/Services/AndroidSystemBrowser.cs implements
IBrowser.InvokeAsync using CustomTabsIntent.LaunchUrl and waits
for MainActivity.AndroidOidcCallbackSink to deliver the deep-link
Intent (android://postit-signin?code=...&state=...).
* PostIt/Services/Platform.cs is a tiny static indirection the
shared library uses to ask the running platform for an
IBrowser and the appropriate default RedirectUri, without
referencing any UI framework from the shared assembly.
* LoginPageViewModel reads Platform.DefaultRedirectUri and
Platform.CreateBrowser().Invoke() before calling LoginAsync.
* PostIt.Android/PlatformBootstrap.cs wires the Android side at
startup, and MainActivity.OnCreate calls EnsureInitialized().
* Xamarin.AndroidX.Browser 1.8.0 added to the central package
versions so CustomTabsIntent resolves.
PostIt is a desktop/mobile app talking to Yavsc.Org
(https://yavsc.pschneider.fr) as an OIDC identity provider. The
previous grant used the client_credentials flow with a client_secret
embedded in postit-settings.json: this was both insecure (secret
travels with the binary) and inappropriate for an interactive app
(token had no user identity, so the API could not scope or audit).
The new flow is Authorization Code + PKCE:
* PostIt client (Settings/AuthenticationSettings.cs): the
ClientSecret property is removed; GetOidcClientOptions now drops
the secret and accepts an optional IBrowser supplied per-platform.
* Settings.cs: new AndroidRedirectUri constant ('android://postit-signin')
that the Android app uses; RedirectUri is no longer hard-coded in
MainViewModel.
* MainViewModel.cs: the manual discovery + client_credentials POST is
replaced with OidcClient.LoginAsync (Authorization Code + PKCE).
* Settings sample: Authority points at the real Yavsc.Org OP, not at
a non-existent Keycloak-style realm path.
* Yavsc.Org/Extensions/HostingExtensions.cs: the 'postit' client seed
is now idempotent (MigratePostItClientToPublic) and detects
legacy state on existing ConfigurationDb rows - flips
RequireClientSecret=false, RequirePkce=true, drops any ClientSecret
row, and replaces the legacy RedirectUris
(https://yavsc.pschneider.fr/, yavsc://callback) with the current
set (http://127.0.0.1:7890/, android://postit-signin).
PostIt.Android:
* MainActivity: explicit Name attribute so the activity alias can
target a stable component; LaunchMode.SingleTask so the existing
instance receives the deep-link Intent; OnNewIntent forwards the
callback URI through AndroidOidcCallbackSink.
* AndroidManifest.xml: activity-alias PostIt.Android.OidcCallbackActivity
exposing scheme=android host=postit-signin to Android, so the OP
redirect lands back in the running PostIt instance.
The IdentityModel.OidcClient.Browser.SystemBrowser package and a
thin AndroidSystemBrowser implementation are added in a follow-up so
OidcClient.LoginAsync can actually drive Chrome Custom Tabs and
consume AndroidOidcCallbackSink.
Selenium-driven UI tests don't run reliably on Linux; the UI tests in
FirstUIStript.cs were flaky and time-consuming without catching real
regressions. The maintained UI going forward is PostIt, which is tested
via its own PostIt.Tests project.
Removed:
- src/Yavsc.Org.Tests/FirstUIStript.cs (the Selenium-based FirstScript class)
- Selenium.WebDriver PackageReference from Yavsc.Org.Tests.csproj
- Selenium.WebDriver version from src/Yavsc.Org.Tests/Directory.Packages.props
WebServerFixture, BaseTestContext, and the integration tests that depend
on them (Remoting, Services, EMailling, etc.) are unaffected.
Move product-local package versions out of the root Directory.Packages.props
into per-product props files under src/<Product>/. The root file now only
contains versions for packages declared by two or more top-level products,
which is the actual shared set.
Each per-product Directory.Packages.props imports the root via
GetPathOfFileAbove so that the shared versions are inherited; this is
necessary because the .NET SDK picks the closest Directory.Packages.props
in the hierarchy and does not merge multiple ones.
Per-product file contents:
- src/cli/ Microsoft.AspNetCore.Razor.Language,
Microsoft.Extensions.{CommandLineUtils,Configuration,Hosting}
- src/PostIt/ Avalonia* and CommunityToolkit.Mvvm
- src/PostIt.Tests/ Avalonia.Headless{,XUnit}
- src/Yavsc.Org/ AsciiDocSharp*, Google.Apis.Compute.v1,
HigginsSoft.IdentityServer8.AspNetIdentity,
IdentityServer8.EntityFramework.Storage,
IdentityServer8.Security, IdentityServer8.Storage,
Microsoft.AspNetCore.Antiforgery, Authentication.Google,
Diagnostics.EntityFrameworkCore, Mvc.NewtonsoftJson,
SignalR, EntityFrameworkCore.Tools, Swashbuckle,
System.Security.Cryptography.Pkcs, YamlDotNet
- src/Yavsc.Org.Tests/ Microsoft.AspNetCore.Hosting,
Extensions.Caching.Memory, Options,
Options.ConfigurationExtensions,
Selenium.WebDriver, xunit.v3.{common,extensibility.core}
- src/Yavsc.Server/ Anthropic.SDK, Google.Apis.Calendar.v3,
Magick.NET-Q8-AnyCPU, MailKit, MimeKit,
Microsoft.AspNetCore.Http.Features, StaticFiles,
EntityFrameworkCore.SqlServer,
Npgsql.EntityFrameworkCore.PostgreSQL,
PayPalMerchantSDK, pazof.rules, RazorEngine.NetCore
- src/Yavsc.Web/ IdentityModel.AspNetCore
No per-product file is created for Yavsc.Api, Yavsc.Blogs, Yavsc.Abstract,
or templateWeb: Api and Blogs only declare the shared JwtBearer, Abstract
and templateWeb declare no package references at all.
Also includes a minor cosmetic update to FirstUIStript.cs (Firefox -> Chrome
driver, dedent, comment header). Tests previously failing on DataProtection
keyset / SMTP were unrelated environment issues (resolved by fixing the
SMTP password locally).
Move the integration test project from the top-level test/ directory into
src/ alongside the projects it tests. Rename the project (and folder) to
Yavsc.Org.Tests to match .NET conventions and reflect that it tests the
Org runtime primarily.
Path changes:
- test/yavscTests/yavscTests.csproj -> src/Yavsc.Org.Tests/Yavsc.Org.Tests.csproj
- All .cs / .json / .resx files moved to their new location
- PostItViewModelTests moved out to the dedicated src/PostIt.Tests project
(it was unrelated to Org testing)
Build adjustments:
- <ProjectReference> paths shortened (..\..\src\X -> ..\X)
- PostIt project reference removed (covered by its own test project)
- <OutputType>exe added (required by xunit.v3)
- xunit.v3.common and xunit.v3.extensibility.core added to package versions
Solution + sln:
- yavsc.sln Project Name updated to 'Yavsc.Org.Tests' and path updated
- GUID preserved so existing build configs stay valid
Static web assets:
- The CopyStaticWebAssetsManifest target was hard-coding the destination
filename to 'testhost.staticwebassets.endpoints.json', which worked
when the assembly was named 'yavscTests'. Now that the assembly name
is 'Yavsc.Org.Tests', ASP.NET Core's MapStaticAssets() looks for
'Yavsc.Org.Tests.staticwebassets.endpoints.json' (entry-assembly-based
resolution). Use $(MSBuildProjectName) so the copy target stays
correct under any future rename.
The Site:Audience setting was conflating two distinct concepts: an OAuth
JWT audience (a single resource identifier) and a CORS allow-list (an
array of origins). Collapsing them caused several latent bugs:
- OAuth/JWT validation expected a single string while CORS WithOrigins
accepts an array.
- Password-reset callback URLs and OAuth client RedirectUri/Origin were
being built from what was meant to be an audience identifier, not a
base URL.
- Yavsc.Org's main CORS policy was hardcoded to '*', with no way to
restrict it without code changes.
Changes:
- SiteSettings.Audience (string) replaced with CorsAllowedOrigins
(IList<string>).
- OAuth JWT Authority still reads Site:Authority; Audience now reads
Site:ExternalUrl (Org only; Api/Blogs use ValidateAudience=false).
- MailSender and AccountController build reset-callback URLs from
Site:ExternalUrl.
- ClientController uses Site:ExternalUrl for OAuth RedirectUri/Origin
defaults on newly created clients.
- Yavsc.Api and Yavsc.Blogs now read CORS origins from
Site:CorsAllowedOrigins instead of hardcoded URLs.
Add shared AddYavscCors / AddYavscJwtBearer extension methods in
Yavsc.Server/Helpers/ServiceExtensions.cs to enforce a single
configuration contract across all runtime services (Api, Blogs, Org).
Fails closed when CorsAllowedOrigins is empty; fails fast at startup
when Site:Authority is missing.
Remove obsolete ConfigurationHelpers.GetAudience (no remaining callers).
Local appsettings-*.json files (which carry deployment-specific values
and are gitignored) must be updated to add Site:CorsAllowedOrigins.
Drops 1038 files from src/Yavsc.Org/wwwroot/lib/ — they remain
on disk and are now restored via 'npm install' at build time
(see package.json and esbuild.config.mjs).
Exception: jonthornton-Datepair is not on npm, the bundled
files are kept in wwwroot/lib/jonthornton-Datepair/ as static
assets.
Also extends .gitignore to ignore:
- node_modules/, build/, package-lock.json (esbuild toolchain)
- wwwroot/js/*.min.js (regenerated by 'npm run build:js')
- .Production.env (added explicitly, not matched by '.*.env'
glob in some git versions)
This aligns themeok with the architecture already in place
on refac/js-bundle (commits ed7522c5, 196f4b0b, 292c0a2f on
that branch). The build artifacts were already present in
node_modules/ and build/ on disk; this commit only stops
tracking them.
Tested: dotnet test 11/11 green (no C# code touched).