Skip to content
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

Fix customer subject validation #2385

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

GAlexIHU
Copy link
Contributor

@GAlexIHU GAlexIHU commented Mar 7, 2025

Overview

  • Check when creating a subscription that if there are entitlements or metered billables, a subject must be defined for the customer
  • Only set customer currency to subscription currency if the subscription has billables
  • Don't allow updating a customer's subejctkeys if they have an active subscription

Summary by CodeRabbit

  • New Features
    • Enhanced validations during subscription creation and updates, ensuring that customer data meets required criteria for subject keys and currency consistency.
    • Improved checks for subscriptions with entitlements, billable items, and metered billables to ensure proper eligibility.
    • Strengthened customer update validations to prevent unauthorized changes when active subscriptions exist.
    • Simplified methods in SubscriptionPhaseSpec for checking entitlements and billables, improving readability and efficiency.
    • Additional validation to ensure required services are provided during validator instantiation.

@GAlexIHU GAlexIHU added the release-note/bug-fix Release note: Bug Fixes label Mar 7, 2025
@GAlexIHU GAlexIHU requested a review from a team as a code owner March 7, 2025 13:20
Copy link

coderabbitai bot commented Mar 7, 2025

📝 Walkthrough

Walkthrough

This pull request modifies the subscription and customer validation logic across multiple modules. Key changes include adding a new customerService parameter to the NewValidator function and updating its invocation. The validator now checks for a non-nil customerService during instantiation. Additionally, the Create and Update methods in the subscription service have been enhanced with validations for customer subject keys and nested currency consistency checks. The HasEntitlements and HasMeteredBillables methods in the subscription specification have been streamlined for improved readability.

Changes

Files Change Summary
app/common/subscription.go, openmeter/subscription/validators/.../validator.go Updated the NewValidator invocation and signature to include an additional customerService parameter; added a check for non-nil customerService in the NewValidator function.
openmeter/subscription/service/service.go Enhanced the Create and Update methods by adding validations for customer subject keys and nesting currency consistency checks when billables are present.
openmeter/subscription/subscriptionspec.go Modified the HasEntitlements and HasMeteredBillables methods to utilize the lo.SomeBy function for improved readability and efficiency.
✨ 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 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.

turip
turip previously approved these changes Mar 7, 2025
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: 5

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b08ddb7 and 624ba54.

📒 Files selected for processing (4)
  • app/common/subscription.go (1 hunks)
  • openmeter/subscription/service/service.go (4 hunks)
  • openmeter/subscription/subscriptionspec.go (2 hunks)
  • openmeter/subscription/validators/customer/validator.go (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: CI
  • GitHub Check: Analyze (go)
🔇 Additional comments (11)
app/common/subscription.go (1)

95-95: Adoption of extended validator constructor

Passing customerService into NewValidator aligns with the enhanced validation needs. The error handling is straightforward and gracefully prevents partial initialization.

openmeter/subscription/service/service.go (6)

60-60: Comment update only

No functional logic is introduced or modified here; the updated comment is clear.


83-89: Currency mismatch check for billable subscriptions

Requiring the customer’s currency to match the subscription currency helps avoid inconsistencies. The check is succinct and properly returns an error on mismatch.


151-152: Auto-set customer currency for first paid subscription

Assigning the subscription’s currency when the customer’s currency is unset is sensible. However, be mindful of concurrency or simultaneous subscription requests that might overwrite or race.

Would you like a script to detect concurrency handling patterns in the repository (e.g., usage of transactions) to confirm consistency?


210-220: Comment update only

This mirrors the create method’s approach to fetching and validating the customer. No additional logic changes introduced.


223-230: Duplicate subject key validation logic

See the comment for lines 73-81 regarding factoring out the subject key checks into a shared utility.


232-239: Duplicate currency mismatch check

See the comment for lines 83-89 for consistency suggestions.

openmeter/subscription/validators/customer/validator.go (1)

30-31: New field in Validator struct

Adding customerService to the Validator struct aligns with the revised constructor. This maintains clarity and consistency in referencing customer data.

openmeter/subscription/subscriptionspec.go (3)

154-158: Looks good!

This new method checks if any subscription phase has entitlements by delegating to each phase's HasEntitlements() method. The implementation using lo.SomeBy() is efficient and returns early once it finds a phase with entitlements.


160-164: Looks good!

This method follows the same pattern as HasEntitlements(), delegating to each phase's HasBillables() method to determine if the subscription has any billable items.


166-170: Looks good!

This method checks for metered billables across all phases using the same delegation pattern. The implementation is consistent with the other helper methods in this section.

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

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 624ba54 and 0aff9ac.

📒 Files selected for processing (2)
  • openmeter/subscription/subscriptionspec.go (2 hunks)
  • openmeter/subscription/validators/customer/validator.go (1 hunks)
🔇 Additional comments (8)
openmeter/subscription/validators/customer/validator.go (3)

26-26: Field assignment looks correct.
Storing the customerService in the Validator is consistent with the new constructor requirement.


33-33: Field addition is consistent.
Introducing customerService in the Validator struct ensures the validator can now perform customer-based validations.


36-78: Revisit subject key comparison for potential ordering issues.
When comparing subject keys to prevent modifications, the code currently checks each index. If reordering identical keys is meant to be inconsequential, consider using an order-agnostic approach to avoid false positives.

openmeter/subscription/subscriptionspec.go (5)

154-158: Utility method appears correct.
HasEntitlements() succinctly checks phases using lo.SomeBy, providing clear and efficient logic.


160-164: Good use of functional style for checking billables.
HasBillables() similarly reads well, and leverages lo.SomeBy for succinctness.


166-170: Metered billables check is concise.
HasMeteredBillables() efficiently identifies metered billables across phases.


391-395: Entitlements check in phase spec is straightforward.
Using lo.SomeBy on flattened items is both clear and consistent.


397-401: Metered billables check in phase spec is consistent.
Mirrors the approach used at the subscription level, maintaining code clarity.

Comment on lines +16 to +22
func NewValidator(subscriptionService subscription.Service, customerService customer.Service) (*Validator, error) {
if subscriptionService == nil {
return nil, fmt.Errorf("subscription service is required")
}
if customerService == nil {
return nil, fmt.Errorf("customer service is required")
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Ensure coverage for nil-check guard clauses.
The non-nil checks for subscriptionService and customerService are appropriate. Consider adding corresponding test cases to guarantee expected error behavior when either dependency is missing.

@GAlexIHU GAlexIHU force-pushed the fix-customer-subject-validation branch from 0aff9ac to 14cd381 Compare March 11, 2025 13:46
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: 0

🧹 Nitpick comments (1)
openmeter/subscription/validators/customer/validator.go (1)

50-72: Increase test coverage for partial or reordered subject keys.

Consider adding unit tests to confirm (1) that partially updating subject keys is correctly handled, and (2) that any disallowed reordering scenario indeed returns an error. This helps assure validations remain consistent across future changes.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0aff9ac and 14cd381.

📒 Files selected for processing (6)
  • openmeter/subscription/service/service.go (4 hunks)
  • openmeter/subscription/subscriptionspec.go (2 hunks)
  • app/common/subscription.go (1 hunks)
  • openmeter/subscription/validators/customer/validator.go (1 hunks)
  • openmeter/subscription/subscriptionspec.go (1 hunks)
  • openmeter/subscription/validators/customer/validator.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • app/common/subscription.go
  • openmeter/subscription/service/service.go
  • openmeter/subscription/subscriptionspec.go
  • openmeter/subscription/subscriptionspec.go
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: E2E
  • GitHub Check: CI
  • GitHub Check: Analyze (go)
🔇 Additional comments (2)
openmeter/subscription/validators/customer/validator.go (2)

16-16: Add a nil check for customerService in the constructor.

Currently, there is no guard clause verifying that customerService is not nil. Including one will prevent potential runtime errors and make the guard clause for dependencies complete.


33-72: Consider whether reordering subject keys should be allowed.

Right now, a small reordering of keys triggers an error for a customer with active subscriptions, which may or may not align with business requirements. If reordering is inconsequential, use an order-agnostic comparison to avoid false negatives.

}

if cust == nil {
return def, fmt.Errorf("customer is nil")
Copy link
Contributor

Choose a reason for hiding this comment

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

GenericNotFound?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

its different error case, err != nil handles that. this case shouldn't happen

return def, fmt.Errorf("customer is nil")
}

if _, err := cust.UsageAttribution.GetSubjectKey(); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should you handle error differently to nil subject?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The only error is it not having a value. The reason that's the only error is because GetSubjectKey is heuristic, it just selects the first subjectkey. Until subject-customer relation is not figured out properly i'd push this issue out

@GAlexIHU GAlexIHU requested a review from tothandras March 11, 2025 14:15
Comment on lines +84 to +85
if cust.Currency != nil {
if string(*cust.Currency) != string(spec.Currency) {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit

Suggested change
if cust.Currency != nil {
if string(*cust.Currency) != string(spec.Currency) {
if cust.Currency != nil && string(*cust.Currency) != string(spec.Currency) {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release-note/bug-fix Release note: Bug Fixes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants