Commit graph

5 commits

Author SHA1 Message Date
88461786ee
Roll back refacto on Posit.Tests 2026-08-21 16:18:20 +01:00
a44c04ad77
feat(postit): circles+ACL UI, blog fixture→SQLite, seed default user
Bundled end-of-branch commit on feat/postit-acl-members.

PostIt UI for circles + per-post ACL
- Reorganise PostIt.Tests into Auth/ and Blogs/ subfolders
  (Bearer/OIDC scope tests vs. blog API fakes live where they
  belong) and introduces PostItHeadlessCollection so the
  Avalonia.Headless tests share a single xUnit collection
  instead of contending with the EF-Core test host.
- Adds BlogAclApiTests (a brand-new behavioural layer over
  POST /api/v1/blogacl) and the fakes it relies on
  (BlogApiTestFakes, BlogPostAuthorDtoTests, AddCircleMember
  DialogTests); pulls UserId-through-OIDC-sub path into
  BearerScopeTests / FakeAuthorizingBrowser /
  OidcStubAuthority.
- App.axaml.cs gets a small PushPageAsync touch-up the new
  tests rely on.
- Drops UnitTest1.cs (xUnit scaffold, never used).

Yavsc.Blogs.Tests — SQLite instead of InMemory
- Bumps Yavsc.Blogs.Tests.csproj on
  Microsoft.EntityFrameworkCore.Sqlite and rewrites
  BlogsWebServerFixture to hold a single shared
  SqliteConnection (Cache=Shared) for the fixture lifetime,
  with a sync Dispose close to dodge async teardown hangs.
  Reason: the EF Core InMemory provider silently ignores FKs,
  which masked the kind of bug we are about to pin in the
  ACL tests. SQLite enforces them, so any future INSERT that
  forgets to seed its parent rows fails loudly here instead
  of passing the test and breaking prod.
- PublishEndpointTests and BlogApiSmokeTests get a one-line
  tweak to follow the new connection lifecycle.

Foreign-key fallout: seed the default user in the fixture
- Adds BlogsWebServerFixture.SeedUser(userName). Now that
  SQLite enforces BlogPost.AuthorId → AspNetUsers.Id, every
  test that POST/PUT/DELETE a BlogPost and sends AuthorId=
  'tester' in the payload needs an AspNetUsers row to satisfy
  the FK or it returns 500 with SQLite Error 19.
- BlogApiTests wraps the existing ResetDatabase with a
  ResetAndSeedDefaultUser helper for the six mutating tests;
  the four GET-only and ModelState-only tests keep the bare
  ResetDatabase.
- Side benefit: every test in Yavsc.Blogs.Tests now finishes
  cleanly instead of hanging at teardown — previously a stuck
  test held the shared SqliteConnection open and the next
  tests waited indefinitely.

Verified: dotnet test src/Yavsc.Blogs.Tests passes 25/25
green from a clean run, no fixture teardown hang.
2026-08-20 23:59:21 +01:00
333b066e66 Identity reloaded 2026-07-05 23:56:10 +01:00
16508e9fb2 postit: replace loopback HTTP listener with custom URI scheme
OAuth2 redirect handling for the desktop PostIt app now follows
RFC 8252 §7.1: the redirect URI is a custom scheme
(postit://callback) that the OS routes back to PostIt instead of
a 127.0.0.1 HTTP listener. The browser hits the scheme, the OS
launches a fresh PostIt process, that process hands the URL to
the running instance over a named pipe, then exits.

Architecture:
  - SingleInstance: cross-platform named-pipe helper. TryHandOffAsync
    is what the 2nd instance calls to forward its command-line URL;
    StartServerAsync runs on the 1st instance and pumps URLs into
    a callback (the running CustomSchemeBrowser).
  - CustomSchemeBrowser: IBrowser that opens the system browser on
    the authorize URL and blocks until the named pipe yields the
    callback URL. No HTTP listener, no port to bind or release,
    no HttpListener lifecycle to babysit.
  - Platform.DefaultRedirectUri is now postit://callback. The
    CustomScheme property exposes the prefix for the redirect
    validator.
  - App.OnFrameworkInitializationCompleted detects a 2nd-instance
    launch by scanning command-line args for the scheme prefix,
    hands the URL off, and exits before opening a window. The
    first instance starts normally and only the browser is
    replaced.

What still has to happen on the user's machine:
  - Registering the postit:// scheme with the OS (a one-time
    setup step: .desktop file on Linux, registry key on Windows,
    Info.plist / LSSetDefaultHandlerForURLScheme on macOS). The
    code already validates EndUrl starts with the configured
    scheme, so a missing registration surfaces as a clear error
    from CustomSchemeBrowser rather than a silent hang.

Removed:
  - LoopbackBrowser and LoopbackBrowserTests — the listener,
    the timeout, the double Stop/Close dance. The whole class of
    'port already bound' / 'next launch fails' issues goes away.
  - The /tests/LoopbackBrowserTests.cs regression coverage is
    obsolete: there is no listener to release anymore. The single-
    instance hand-off is covered by the existing tests on the
    OidcClient flow path.

Tests: PostIt.Tests 17/17 pass, Yavsc.Org.Tests 13/14 (the one
remaining failure is SendEMailSynchrone, pre-existing and
unrelated to this change).
2026-06-22 00:53:01 +01:00
c411445699 postit: test LoginPageViewModel against an in-memory OIDC authority
Add a stubbed OIDC authority (discovery, jwks, /connect/token,
/connect/userinfo) and a fake IBrowser, then cover the full
authorization-code + PKCE flow in LoginPageViewModelTests.

The new LoginPageViewModel(Settings, Func<IBrowser?>) constructor
plus the BrowserFactoryOverride property keep production wiring
unchanged: the existing parameterless ctor and the platform
projects' Platform.CreateBrowser still drive runtime.
2026-06-20 20:52:00 +01:00