Migrate Hub billing page to the api's session-first flow#179
Migrate Hub billing page to the api's session-first flow#179tobihagemann wants to merge 4 commits into
Conversation
…g-api-migration Conflicts in assets/js/hubsubscription.js and layouts/hub-billing/single.html were resolved by keeping this branch's versions wholesale: both sides rewrote the same billing-page flow (this branch targets the new api manage/checkout endpoints, develop's store-migration phases 1+2 kept the legacy store flow with an api billing-session bootstrap), so a line-level merge is not meaningful. Dropped from develop as superseded: customer lookup with redacted email, the /billing/session + ?session= confirmation-link bootstrap, and token_transfer=session delivery back to the Hub (this branch currently only delivers the license via ?token=).
…sion-authorized manage and checkout
WalkthroughThis PR reworks the Hub billing subscription flow to support both card and invoice payment methods. Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (4)
data/de/eu_countries.yaml (1)
1-54: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider alphabetical ordering for the country dropdown.
Entries are listed in EU accession/treaty order rather than alphabetically by name (e.g.,
Frankreich,Deutschland,Griechenlandappear out of alphabetic sequence). Since this list feeds a<select>populated via{{ range (index $.Site.Data $.Site.Language.Lang).eu_countries }}inlayouts/hub-billing/single.html, sorting by localized name would improve usability for users scanning the dropdown.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@data/de/eu_countries.yaml` around lines 1 - 54, The eu_countries list is not sorted alphabetically by localized country name, which makes the dropdown harder to scan. Reorder the entries in eu_countries so the names appear in alphabetical sequence while keeping the same code/name pairs, and ensure the list consumed by the range in layouts/hub-billing/single.html remains alphabetically sorted for the German locale.data/en/eu_countries.yaml (1)
1-54: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winSame ordering concern as the German counterpart.
The English list mirrors the same non-alphabetical accession order (e.g.,
France,Germany,Greeceinterleaved with earlier entries). Sorting both locale files alphabetically by displayed name would make the country picker easier to navigate.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@data/en/eu_countries.yaml` around lines 1 - 54, The English EU country list in eu_countries.yaml should be reordered to match the alphabetical-by-name sorting requested for the German counterpart. Update the entries in the existing country list so the displayed names are in alphabetical order while keeping the same code/name pairs, and keep the ordering consistent with the locale file’s country-picker data structure.layouts/hub-billing/single.html (2)
467-474: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider
aria-pressedon the payment-method toggle buttons.These act as a two-state switcher but don't expose pressed/selected state to assistive tech.
♿ Suggested addition
-<button type="button" ... :class="{...: subscriptionData.paymentMethod === 'card'}" `@click.prevent`="subscriptionData.paymentMethod = 'card'"> +<button type="button" ... :class="{...: subscriptionData.paymentMethod === 'card'}" :aria-pressed="subscriptionData.paymentMethod === 'card'" `@click.prevent`="subscriptionData.paymentMethod = 'card'">🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@layouts/hub-billing/single.html` around lines 467 - 474, The payment-method toggle buttons in the hub billing checkout act like a two-state switch, but their selected state is not exposed to assistive technologies. Update the button markup in the payment method toggle section to include aria-pressed on both buttons, binding it to whether subscriptionData.paymentMethod equals 'card' or 'invoice' so screen readers can announce the active choice.
127-197: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low valueOptional: guard
subscriptionData.details.*accesses against null.
detailsis initialized tonull(line 6) and thesex-show/x-textbindings (status, seats, current_period_end, processor) dereference it directly. If this block is ever reactive beforedetailsis populated (e.g. via a parentx-showrather thanx-if), Alpine will log console errors. Optional chaining would make this resilient regardless of the parent gating mechanism.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@layouts/hub-billing/single.html` around lines 127 - 197, Guard the direct subscriptionData.details dereferences in the hub billing template so Alpine does not evaluate them while details is still null. Update the bindings in the status, seats, current_period_end, and processor checks within the single.html subscription section to use null-safe access or an equivalent guard, especially around the x-show, x-text, and disabled expressions tied to subscriptionData.details. Use the existing subscriptionData object and its details field as the locating symbols when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@data/de/eu_countries.yaml`:
- Around line 1-54: The eu_countries list is not sorted alphabetically by
localized country name, which makes the dropdown harder to scan. Reorder the
entries in eu_countries so the names appear in alphabetical sequence while
keeping the same code/name pairs, and ensure the list consumed by the range in
layouts/hub-billing/single.html remains alphabetically sorted for the German
locale.
In `@data/en/eu_countries.yaml`:
- Around line 1-54: The English EU country list in eu_countries.yaml should be
reordered to match the alphabetical-by-name sorting requested for the German
counterpart. Update the entries in the existing country list so the displayed
names are in alphabetical order while keeping the same code/name pairs, and keep
the ordering consistent with the locale file’s country-picker data structure.
In `@layouts/hub-billing/single.html`:
- Around line 467-474: The payment-method toggle buttons in the hub billing
checkout act like a two-state switch, but their selected state is not exposed to
assistive technologies. Update the button markup in the payment method toggle
section to include aria-pressed on both buttons, binding it to whether
subscriptionData.paymentMethod equals 'card' or 'invoice' so screen readers can
announce the active choice.
- Around line 127-197: Guard the direct subscriptionData.details dereferences in
the hub billing template so Alpine does not evaluate them while details is still
null. Update the bindings in the status, seats, current_period_end, and
processor checks within the single.html subscription section to use null-safe
access or an equivalent guard, especially around the x-show, x-text, and
disabled expressions tied to subscriptionData.details. Use the existing
subscriptionData object and its details field as the locating symbols when
making the change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3c864dee-8dad-4a11-9584-0c965e44e55e
📒 Files selected for processing (7)
assets/js/hubsubscription.jsdata/de/eu_countries.yamldata/en/eu_countries.yamli18n/de.yamli18n/en.yamllayouts/hub-billing/single.htmllayouts/partials/hub-license-block.html
Important
Requires cryptomator/api#34 (and its base cryptomator/api#33) to be deployed. The page hard depends on the new endpoints, so both sides need to ship together.
Moves the Hub billing page off the legacy store's manage endpoints and onto the api, with the billing session as the single credential. Opening the page from a Hub now starts with a customer lookup (redacted email for known Hubs, email entry for new ones) and a confirmation link. The emailed
?session=link resolves the session and routes on itsbillingId: linked sessions go to the manage view, new customers to checkout (card via Paddle, invoice via the new EspoCRM checkout). Manage calls authorize withAuthorization: Bearer <session>, checkouts carry the session so the purchase gets linked back, and the license comes fromGET /licenses/hub?session=&legacy=without a captcha. Delivery back to the Hub honorstoken_transfer:?token=for older Hubs,?session=for newer ones. Expired or reused links get their own screen.State Machine