8 Commits

Author SHA1 Message Date
HolgerHatGarKeineNode 29628b41e9 Add lecturer cleanup job and update profile update functionality
- 🧹 Introduce `lecturers:cleanup` command to delete lecturers without associated courses or events, merging their items into "Einundzwanzig."
- ⚙️ Add `update` method to `UserController` for handling profile updates, allowing name changes while restricting role modifications.
- 🌐 Register `PATCH /api/user` route for profile updates and update related API tests.
- 🧪 Add feature and console tests for `lecturers:cleanup`, covering dry-run, forced deletion, and edge cases.
2026-06-16 14:40:40 +02:00
HolgerHatGarKeineNode f9b3428865 Add DELETE /api/mobile/token so the app can revoke its token on logout 2026-06-12 15:12:38 +02:00
HolgerHatGarKeineNode 76787a1bee Render the handoff page directly instead of 302-redirecting to /app/auth
Chrome follows a server 302 internally and never dispatches the /app/auth
App Link, so the handoff page stayed in the browser and the token never
reached the app. The signed callback (and complete/confirm) now render
the handoff page directly with the einundzwanzig:// deep-link button — the
signer opens the callback in the browser, the user lands on the handoff
page and taps once to return to the app, which stores the token.
2026-06-12 00:29:44 +02:00
HolgerHatGarKeineNode 64a5fcd9f1 Make the mobile login page Lightning-only
The Nostr login is now driven entirely by the app (it launches the
NIP-55 signer via an ACTION_VIEW intent and posts the signed event to
/auth/mobile/signed), so the portal page no longer needs window.nostr or
an Amber button — it only renders the Lightning QR. The path-based
signer callback and token exchange endpoints remain server-side.
2026-06-11 21:51:01 +02:00
HolgerHatGarKeineNode c30f1932e4 Use window.nostr (NIP-46/Amber bunker) on the mobile login page
Replaces the fragile NIP-55 intent/callback round-trip with the same
mechanism the desktop login uses: openNostrLogin signs the session
challenge via window.nostr — provided by an extension or by
window.nostr.js over a persistent NIP-46 connection (Amber pairing with
permissions). The listener stores a LoginKey for the page's k1 and
navigates to the completion route, which issues the token and redirects
into the app via the verified App Link handoff.
2026-06-11 20:47:02 +02:00
HolgerHatGarKeineNode 7531f28f22 Add verified App Link handoff and mobile token exchange endpoint
Replaces the custom-scheme auto-redirect (which triggers Chrome's
confirmation prompt) with a verified Android App Link handoff:

- public/.well-known/assetlinks.json for space.einundzwanzig.mobile
  (debug cert fingerprint; add the release cert before store builds)
- GET /app/auth handoff: opens the app directly when the App Link is
  verified; renders a button-based fallback page otherwise
- POST /api/mobile/token: trades a NIP-55-signed login event for a
  Sanctum token — used when Amber's callback opens the app directly
- complete/confirm/signedCallback now redirect to the handoff URL
2026-06-11 19:51:14 +02:00
HolgerHatGarKeineNode 4aba1514e9 Make the NIP-55 signer callback robust against Amber URL rewriting
Amber drops the query string when it rebuilds the callback URL and
appends the signed event directly to the path. The mobile login page now
hands out path-based callback URLs (/auth/mobile/signed/{k1}/) so the
event arrives as the remainder of the path.

The new callback runs in the web middleware group: the signer opens it
in the system browser, which shares cookies with the in-app browser
session, so the flow completes immediately — a bridge page issues the
token and fires the einundzwanzig:// deep link. The LoginKey row is
still written as a fallback for the polling login page.
2026-06-11 18:43:59 +02:00
HolgerHatGarKeineNode 07169dfee6 Add mobile app auth flow with Sanctum token handoff via deep link
The Einundzwanzig mobile app opens /auth/mobile in an in-app browser.
After a Lightning (LNURL) or Nostr login the flow issues a personal
access token and hands it back via the einundzwanzig://auth deep link.

- New auth.mobile-login Livewire view: Lightning QR (shared k1) plus
  Nostr signing via NIP-55 Android signers (Amber) with server callback,
  and a confirmation screen for already authenticated sessions
- MobileAuthController: NIP-55 callback verification, completion route
  issuing the token (replacing same-device tokens), redirect whitelist
- Nostr login event verification and npub user resolution extracted to
  App\Support\NostrLogin, now shared with the interactive login
- GET /api/user (auth:sanctum) returns the token owner's profile
2026-06-11 18:01:50 +02:00