Skip to content

Show usage and billing for self-hosted instances #3290

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 25, 2025

Conversation

carlosmonastyrski
Copy link
Contributor

@carlosmonastyrski carlosmonastyrski commented Mar 21, 2025

Description 📣

On self-hosted instances, the "Usage & Billing" tab will now be visible. Initially, only the first tab will be displayed, showing available features, their usage (currently calculating the first three features, similar to the license server), and providing a redirect to Infisical’s pricing page when the upgrade button is clicked.
CleanShot 2025-03-21 at 13 51 57

CleanShot 2025-03-21 at 14 02 43

Type ✨

  • Bug fix
  • New feature
  • Improvement
  • Breaking change
  • Documentation

Tests 🛠️

# Here's some code block to paste some code snippets

Summary by CodeRabbit

  • New Features
    • Enhanced billing and license management now provide a more informative and dynamic billing view.
    • The "Usage & Billing" link is now always visible in the sidebar for improved accessibility.
    • The billing page experience has been refined with upgrade options and tab displays that adjust based on whether you’re on a cloud-based or self-hosted instance.
    • New constants for billing plan features and table headers have been introduced for better clarity in billing information.

Copy link

coderabbitai bot commented Mar 21, 2025

Walkthrough

The changes update both backend and frontend functionalities related to billing and licensing. In the backend, a new TypeScript file defines constants for billing plan configurations, and the license service has been enhanced with additional data access layers and logic to handle various instance types. The service now distinguishes between cloud and self-hosted instances by adjusting member counting and table generation processes accordingly. In the server routes, the license service initialization has been updated to include the new dependencies. On the frontend, conditional checks based on the window’s origin have been removed from the sidebar components, ensuring the “Usage & Billing” link is always displayed. Additionally, billing components have been updated to conditionally modify the behavior and labeling of upgrade buttons and tabs based on the instance type.

Suggested reviewers

  • DanielHougaard
  • sheensantoscapadngan
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
frontend/src/pages/organization/BillingPage/components/BillingTabGroup/BillingTabGroup.tsx (1)

19-26: Conditionally filter tabs based on instance type.

The implementation correctly identifies cloud instances and filters tabs accordingly. For self-hosted instances, only the relevant "Infisical Self-Hosted" tab is shown.

There's a minor inconsistency in the key naming. When isCloudInstance is false, you're using key: "tab-infisical-cloud" for the "Infisical Self-Hosted" tab. Consider updating this to use the correct key:

- : [{ name: "Infisical Self-Hosted", key: "tab-infisical-cloud" }];
+ : [{ name: "Infisical Self-Hosted", key: "tab-infisical-self-hosted" }];
frontend/src/pages/organization/BillingPage/components/BillingCloudTab/PreviewSection.tsx (2)

53-57: Consider externalizing environment checks.
Hardcoding domain checks in isCloudInstance can be fragile if the deployment origin changes. Consider storing or inferring this information from environment variables or configuration to avoid potential mismatches in the future.


159-176: Consider adding error handling when opening portal session.
If createCustomerPortalSession.mutateAsync fails, there is no user feedback. You might wrap this in a try/catch to show an error message for a better user experience.

+ try {
    const { url } = await createCustomerPortalSession.mutateAsync(currentOrg.id);
    window.location.href = url;
+ } catch (error) {
+   console.error(error);
+   // Optionally display UI notification
+ }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 524462d and 9924ef3.

📒 Files selected for processing (7)
  • backend/src/ee/services/license/licence-enums.ts (1 hunks)
  • backend/src/ee/services/license/license-service.ts (7 hunks)
  • backend/src/server/routes/index.ts (1 hunks)
  • frontend/src/layouts/OrganizationLayout/ProductsSideBar/DefaultSideBar.tsx (1 hunks)
  • frontend/src/layouts/OrganizationLayout/components/MinimizedOrgSidebar/MinimizedOrgSidebar.tsx (1 hunks)
  • frontend/src/pages/organization/BillingPage/components/BillingCloudTab/PreviewSection.tsx (5 hunks)
  • frontend/src/pages/organization/BillingPage/components/BillingTabGroup/BillingTabGroup.tsx (1 hunks)
🧰 Additional context used
🧬 Code Definitions (3)
backend/src/server/routes/index.ts (1)
backend/src/ee/services/license/license-service.ts (1) (1)
  • licenseServiceFactory (62-667)
frontend/src/layouts/OrganizationLayout/components/MinimizedOrgSidebar/MinimizedOrgSidebar.tsx (1)
frontend/src/components/v2/Dropdown/Dropdown.tsx (1) (1)
  • DropdownMenuItem (82-106)
backend/src/ee/services/license/license-service.ts (1)
backend/src/ee/services/license/licence-enums.ts (2) (2)
  • BillingPlanRows (1-19)
  • BillingPlanTableHead (21-24)
🪛 Biome (1.9.4)
frontend/src/pages/organization/BillingPage/components/BillingTabGroup/BillingTabGroup.tsx

[error] 32-32: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Check Frontend Type and Lint check
  • GitHub Check: Run integration test
  • GitHub Check: Check TS and Lint
🔇 Additional comments (22)
frontend/src/layouts/OrganizationLayout/ProductsSideBar/DefaultSideBar.tsx (1)

15-21: Accessibility improvement to display Usage & Billing for all instances.

The code change makes the "Usage & Billing" navigation link unconditionally visible in the DefaultSideBar component, aligning with the PR objective to show usage and billing for self-hosted instances.

backend/src/ee/services/license/licence-enums.ts (2)

1-19: Well-structured billing plan configuration constants.

The BillingPlanRows constant provides a clear definition of all the features that can be tracked for billing purposes. This aligns perfectly with the PR objective of showing usage metrics for self-hosted instances.


21-24: Good definition of table headers for usage display.

The BillingPlanTableHead constant defines a simple and clear structure for displaying the "Allowed" and "Used" columns in the billing UI, which will be essential for showing usage metrics.

frontend/src/layouts/OrganizationLayout/components/MinimizedOrgSidebar/MinimizedOrgSidebar.tsx (1)

373-377: Accessibility improvement to display Usage & Billing for all instances.

The code change makes the "Usage & Billing" navigation link unconditionally visible in the MinimizedOrgSidebar component, consistent with the change in DefaultSideBar and aligning with the PR objective to show usage and billing for self-hosted instances.

frontend/src/pages/organization/BillingPage/components/BillingTabGroup/BillingTabGroup.tsx (1)

38-50: Conditionally render tab panels for cloud instances.

This change correctly implements conditional rendering for cloud-specific tab panels, ensuring they're only displayed when appropriate. The approach helps maintain a clean user interface for self-hosted instances.

backend/src/server/routes/index.ts (1)

416-423: New dependencies in license service look correct.
The newly added identityOrgMembershipDAL and projectDAL are logically consistent with the enhanced billing and licensing features. Ensure tests cover these integrations to confirm that they properly support any additional logic.

frontend/src/pages/organization/BillingPage/components/BillingCloudTab/PreviewSection.tsx (4)

62-66: Fallback behavior for self-hosted is clear.
The condition correctly opens the pricing page for self-hosted instances. No concerns here.


84-95: Upgrade label logic is clear.
The getUpgradePlanLabel function correctly distinguishes between cloud vs. self-hosted instances and trial usage. This is concise and easy to maintain.


123-123: Upgrade label usage confirmed.
Using getUpgradePlanLabel() directly within the button is concise and maintains a clear separation of presentation from logic.


189-189: Graceful fallback for missing date.
Displaying a dash instead of a date is a clear and user-friendly approach if currentPeriodEnd is not set.

backend/src/ee/services/license/license-service.ts (12)

15-15: Import for identity org DAL.
The import statement for TIdentityOrgDALFactory is aligned with newly introduced logic.


17-17: Import for project DAL.
Similarly, this import integrates well with the extended project-based licensing logic.


21-21: Importing BillingPlanRows and BillingPlanTableHead.
Using these constants centralizes plan configuration data and helps keep your feature table consistent.


34-35: Offline license type imports.
The references to TOfflineLicense and TOfflineLicenseContents are properly declared.


46-52: Updated service factory dependency type.
The addition of identityOrgMembershipDAL and projectDAL to TLicenseServiceFactoryDep is well-organized. The use of Pick for minimal exposure of methods is a good practice.


66-66: Injecting keyStore into the factory.
No issues. The injection is consistent with the rest of the service’s design.


68-69: Injecting identityOrgMembershipDAL and projectDAL.
Properly passes in new dependencies for membership and project-based usage calculations.


73-74: Introducing selfHostedLicense variable.
The new selfHostedLicense reference will store offline license details. This is straightforward and clear.


138-138: Assigning selfHostedLicense.
Storing the offline license post-verification is correct. Consider logging license metadata for debugging if needed.


362-366: Billing data fetch for non-on-prem.
The short-circuit logic to retrieve cloud-plan billing info is clean. The fallback for self-hosted flows is handled below.


390-394: Plan table retrieval for cloud instances.
This block parallels the billing retrieval logic above. The usage of early return ensures on-prem logic is bypassed.


397-417: Mapping plan rows for on-prem usage.
Iterating over BillingPlanRows and populating used counts from orgDAL, projectDAL, and identityOrgMembershipDAL is both extensible and uniform.

@carlosmonastyrski carlosmonastyrski requested review from akhilmhdh and sheensantoscapadngan and removed request for scott-ray-wilson and akhilmhdh March 24, 2025 13:29
Copy link
Member

@sheensantoscapadngan sheensantoscapadngan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm getting this upon viewing the billing page in my local setup
image

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
frontend/src/pages/organization/BillingPage/components/BillingTabGroup/BillingTabGroup.tsx (1)

27-29: ⚠️ Potential issue

Add missing key prop to mapped Tab elements.

React requires a unique key prop for elements in an iterable to help with rendering optimization.

Apply this diff to fix the issue:

- {tabsFiltered.map((tab) => (
-   <Tab value={tab.key}>{tab.name}</Tab>
- ))}
+ {tabsFiltered.map((tab) => (
+   <Tab key={tab.key} value={tab.key}>{tab.name}</Tab>
+ ))}
🧰 Tools
🪛 Biome (1.9.4)

[error] 28-28: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9924ef3 and 9a5633f.

📒 Files selected for processing (3)
  • frontend/src/helpers/platform.ts (1 hunks)
  • frontend/src/pages/organization/BillingPage/components/BillingCloudTab/PreviewSection.tsx (6 hunks)
  • frontend/src/pages/organization/BillingPage/components/BillingTabGroup/BillingTabGroup.tsx (2 hunks)
🧰 Additional context used
🧬 Code Definitions (2)
frontend/src/pages/organization/BillingPage/components/BillingCloudTab/PreviewSection.tsx (1)
frontend/src/helpers/platform.ts (1)
  • isInfisicalCloud (1-5)
frontend/src/pages/organization/BillingPage/components/BillingTabGroup/BillingTabGroup.tsx (1)
frontend/src/helpers/platform.ts (1)
  • isInfisicalCloud (1-5)
🪛 Biome (1.9.4)
frontend/src/pages/organization/BillingPage/components/BillingTabGroup/BillingTabGroup.tsx

[error] 28-28: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Run integration test
🔇 Additional comments (8)
frontend/src/helpers/platform.ts (1)

4-5: Function enhancement with an additional URL check.

The addition of "https://gamma.infisical.com" to the list of cloud URLs expands the function's capability to recognize all Infisical cloud environments, which aligns with the PR objective of showing usage and billing for self-hosted instances.

frontend/src/pages/organization/BillingPage/components/BillingTabGroup/BillingTabGroup.tsx (2)

20-22: Improved conditional rendering based on environment.

The code now intelligently filters tabs based on whether the application is running in an Infisical cloud environment, showing only relevant tabs to self-hosted users.


34-46: Conditional rendering for tab panels enhances UI relevance.

The conditional rendering ensures that tab panels for cloud-specific features are only shown in cloud environments, which provides a cleaner, more relevant UI for self-hosted users.

frontend/src/pages/organization/BillingPage/components/BillingCloudTab/PreviewSection.tsx (5)

51-53: Added null check for better error handling.

This defensive check prevents potential rendering errors when the plan slug is undefined or null.


61-64: Enhanced upgrade button behavior for self-hosted instances.

The button now intelligently redirects self-hosted users to the Infisical pricing page, which aligns with the PR objective of directing users to the appropriate upgrade path based on their environment.


83-94: New function for contextual upgrade button labels.

The getUpgradePlanLabel function elegantly determines the appropriate button label based on the environment and trial status, improving UI context and user experience.


158-175: Conditionally rendered management options for cloud instances.

The "Manage plan" button is now only shown in cloud environments, which is appropriate as self-hosted instances don't have the same plan management workflow.


188-188: Added null check for date formatting.

This defensive check prevents rendering errors when the renewal date is unavailable, which improves the robustness of the component.

@carlosmonastyrski carlosmonastyrski merged commit b6d67df into main Mar 25, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants