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

chore: Segregate organization flags based on orgnization id #39608

Open
wants to merge 4 commits into
base: release
Choose a base branch
from

Conversation

abhvsn
Copy link
Contributor

@abhvsn abhvsn commented Mar 6, 2025

Description

PR to add organizationId param while fetching the organization level flags. This will be useful when one wants to use @FeatureFlagged for server internal calls e.g. Cron job, analytics event which is running on threads which does not have user context directly.

Fixes #Issue Number
or
Fixes Issue URL

Warning

If no issue exists, please create an issue first, and check with the maintainers if the issue is valid.

/test All

🔍 Cypress test results

Tip

🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
Workflow run: https://github.com/appsmithorg/appsmith/actions/runs/13715911767
Commit: 5af72fb
Cypress dashboard.
Tags: @tag.All
Spec:


Fri, 07 Mar 2025 09:01:20 UTC

Communication

Should the DevRel and Marketing teams inform users about this change?

  • Yes
  • No

Summary by CodeRabbit

  • New Features
    • Introduced organization-specific checks that ensure features operate in line with your organization’s configuration.
    • Enhanced retrieval of user context for more consistent and secure operations.
  • Bug Fixes
    • Improved error messaging when required organization details are missing, leading to more stable operation.

Copy link
Contributor

coderabbitai bot commented Mar 6, 2025

Walkthrough

The changes update feature flag handling across the codebase by enforcing the inclusion of an organization ID. Method signatures are modified accordingly, and a new helper class is introduced to retrieve the reactive current user. The caching mechanism for organization feature flags was improved to maintain multiple entries keyed by organization ID. Test cases have been updated and added to verify these behaviors, ensuring that feature flag checks correctly use the organization context.

Changes

File(s) Change Summary
.../aspect/FeatureFlaggedMethodInvokerAspect.java Updated isFeatureFlagEnabled signature to accept organizationId and added extractOrganizationId; now throws an exception if missing.
.../helpers/ReactiveContextUtils.java Introduced new class with getCurrentUser() to retrieve the current user reactively using ReactiveSecurityContextHolder.
.../plugins/solutions/PluginTriggerSolutionCEImpl.java, .../solutions/ce/DatasourceTriggerSolutionCEImpl.java Modified trigger methods to dynamically fetch organization-specific feature flags based on the extracted organization ID.
.../services/ce/FeatureFlagServiceCE.java, .../services/ce/FeatureFlagServiceCEImpl.java Updated getCachedOrganizationFeatureFlags to take an organizationId parameter; refactored the implementation to use a map for caching multiple organizations' feature flags.
.../services/ce/SessionUserServiceCEImpl.java, .../solutions/ce/ActionExecutionSolutionCEImpl.java Deprecated the existing getCurrentUser method in favor of ReactiveContextUtils and updated datasource verification to incorporate organization context.
.../test/** Updated and added tests to validate organization-specific feature flag checks and method signature adjustments, including negative tests for missing organization IDs.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Aspect as FeatureFlaggedMethodInvokerAspect
    participant FFService as FeatureFlagService
    participant UserUtil as ReactiveContextUtils

    Client->>Aspect: Invoke feature flagged method
    Note right of Aspect: Extract organizationId from method args
    Aspect->>FFService: Call isFeatureFlagEnabled(flag, organizationId)
    FFService-->>Aspect: Return flag status
    Aspect->>Client: Proceed with method execution (or throw exception if missing)
Loading

Possibly related PRs

Suggested labels

Enhancement, Task

Suggested reviewers

  • sharat87
  • nidhi-nair

Poem

In code’s embrace, our flags now gleam,
With org IDs guiding each method’s stream.
A tweak here, a change there—logic refined,
Our feature flags are now smartly aligned.
Cheers to progress and a codebase so bright,
🚀 CodeRabbit leaps with all its might!

✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 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.

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.

@github-actions github-actions bot added the skip-changelog Adding this label to a PR prevents it from being listed in the changelog label Mar 6, 2025
@abhvsn
Copy link
Contributor Author

abhvsn commented Mar 6, 2025

Blocked on #39594

Copy link

github-actions bot commented Mar 6, 2025

Failed server tests

  • com.appsmith.server.aspect.FeatureFlaggedMethodInvokerAspectTest#ceEeSyncMethod_ceImplTest
  • com.appsmith.server.aspect.FeatureFlaggedMethodInvokerAspectTest#ceEeSyncMethod_eeImplTest

@abhvsn abhvsn added the ok-to-test Required label for CI label Mar 7, 2025
@abhvsn abhvsn marked this pull request as ready for review March 7, 2025 07:30
@abhvsn abhvsn requested a review from NilanshBansal as a code owner March 7, 2025 07:30
@abhvsn abhvsn requested a review from trishaanand March 7, 2025 07:30
Copy link
Contributor

@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 (9)
app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ReactiveContextUtils.java (1)

1-22: New utility class for reactive user context retrieval.

This new utility class properly extracts the current user from the reactive security context. The implementation handles the empty case appropriately with logging.

Consider adding a null check before casting to User to prevent potential ClassCastException if the principal is of a different type:

-                .map(auth -> (User) auth.getPrincipal())
+                .map(auth -> {
+                    if (auth.getPrincipal() instanceof User) {
+                        return (User) auth.getPrincipal();
+                    }
+                    log.error("Principal is not of type User: {}", auth.getPrincipal().getClass());
+                    return null;
+                })
+                .filter(user -> user != null)
app/server/appsmith-server/src/main/java/com/appsmith/server/plugins/solutions/PluginTriggerSolutionCEImpl.java (1)

89-97: Updated to retrieve organization-specific feature flags.

The implementation now correctly retrieves feature flags using the organization ID from the trigger request, supporting the PR objective to segregate flags by organization.

The TODO comment indicates this is specifically needed for Google Sheets integration. Consider adding more detailed documentation about this requirement if it's intended to be a permanent solution rather than a temporary flag.

app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java (1)

292-292: Consider non-blocking alternatives in production code.

While using .block() is acceptable in test code, be mindful that this pattern shouldn't be carried over to production code as it can lead to thread blocking issues in a reactive application.

app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourceTriggerSolutionCEImpl.java (1)

123-128: Simplify feature flag retrieval logic to avoid redundant calls.

The current implementation makes potentially redundant calls to getCachedOrganizationFeatureFlags. Consider refactoring to reduce duplication:

-Map<String, Boolean> featureFlagMap =
-        featureFlagService.getCachedOrganizationFeatureFlags(organizationId)
-                        != null
-                ? featureFlagService
-                        .getCachedOrganizationFeatureFlags(organizationId)
-                        .getFeatures()
-                : Collections.emptyMap();
+Map<String, Boolean> featureFlagMap;
+var cachedFlags = featureFlagService.getCachedOrganizationFeatureFlags(organizationId);
+if (cachedFlags != null) {
+    featureFlagMap = cachedFlags.getFeatures();
+} else {
+    featureFlagMap = Collections.emptyMap();
+}
app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java (2)

42-42: Consider using a thread-safe data structure.
If multiple threads update or read from this map concurrently, a ConcurrentHashMap or proper synchronization may be necessary.

- private Map<String, CachedFeatures> cachedOrganizationFeatureFlags = new HashMap<>();
+ private Map<String, CachedFeatures> cachedOrganizationFeatureFlags = new ConcurrentHashMap<>();

200-203: Method reliably returns a non-null CachedFeatures.
Since getOrDefault always returns a valid object, external null checks are unnecessary. This can simplify call sites checking for null.

app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImpl.java (1)

766-771: Remove redundant null check for cached features.
getCachedOrganizationFeatureFlags will never return null, so simplify the logic.

- Map<String, Boolean> features =
-     featureFlagService.getCachedOrganizationFeatureFlags(organizationId) != null
-         ? featureFlagService.getCachedOrganizationFeatureFlags(organizationId).getFeatures()
-         : Collections.emptyMap();
+ CachedFeatures orgFeatures = featureFlagService.getCachedOrganizationFeatureFlags(organizationId);
+ Map<String, Boolean> features = orgFeatures.getFeatures();
app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspect.java (2)

76-79: Fix typo in error message

There's a typo in the error message: "orgnization-specific" should be "organization-specific".

-                    "Add missing organizationId parameter and enforce non-null value for orgnization-specific feature flags retrieval in non-reactive methods";
+                    "Add missing organizationId parameter and enforce non-null value for organization-specific feature flags retrieval in non-reactive methods";

132-146: Organization ID extraction logic implementation

The implementation to extract organization ID from method arguments is sound, looking for parameters named either "organizationId" or "orgId". This facilitates feature flag checks for organization-specific contexts.

Consider enhancing this method to support a wider range of parameter naming patterns or potentially using annotations to explicitly mark which parameter contains the organization ID, as relying solely on exact parameter names can be fragile if naming conventions change.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7927d76 and 5af72fb.

📒 Files selected for processing (13)
  • app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspect.java (3 hunks)
  • app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ReactiveContextUtils.java (1 hunks)
  • app/server/appsmith-server/src/main/java/com/appsmith/server/plugins/solutions/PluginTriggerSolutionCEImpl.java (1 hunks)
  • app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCE.java (1 hunks)
  • app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java (3 hunks)
  • app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/SessionUserServiceCEImpl.java (1 hunks)
  • app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImpl.java (2 hunks)
  • app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourceTriggerSolutionCEImpl.java (1 hunks)
  • app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java (5 hunks)
  • app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/TestComponentImpl.java (2 hunks)
  • app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/ce/TestComponentCE.java (1 hunks)
  • app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/ce/TestComponentCEImpl.java (2 hunks)
  • app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java (1)
Learnt from: abhvsn
PR: appsmithorg/appsmith#39171
File: app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java:42-44
Timestamp: 2025-02-24T05:59:14.021Z
Learning: The reactive transition for helper methods consuming @FeatureFlagged annotations will be handled in a separate PR to maintain focused changes and proper separation of concerns.
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: perform-test / client-build / client-build
  • GitHub Check: perform-test / rts-build / build
  • GitHub Check: server-unit-tests / server-unit-tests
  • GitHub Check: server-spotless / spotless-check
🔇 Additional comments (21)
app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCE.java (1)

45-45: Method signature updated to support organization-specific feature flags.

The change adds an organizationId parameter to the getCachedOrganizationFeatureFlags method, aligning with the PR objective to segregate organization flags. This enables feature flag checks to be organization-specific, particularly useful for server-side internal calls.

app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/SessionUserServiceCEImpl.java (1)

37-39: Properly deprecated method with clear migration path.

The method is correctly marked as deprecated with a TODO comment providing clear guidance to use ReactiveContextUtils#getCurrentUser() instead. This supports the refactoring effort for organization-specific feature flags.

app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java (2)

10-10: Good addition of ReactiveContextUtils import.

This import supports the new approach for retrieving the current user and organization context necessary for feature flag segregation.


294-294: Appropriate use of organization context for feature flags.

Good update to pass the organization ID parameter when retrieving cached organization feature flags, which aligns with the PR objective of segregating flags by organization.

Also applies to: 310-310

app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/ce/TestComponentCEImpl.java (2)

30-32: Method signature updated correctly for synchronous operation.

The method has been properly changed from returning Mono<String> to directly returning String, and now includes the required organizationId parameter. This matches the interface declaration changes.


44-47: Good test coverage for organization-less scenario.

Adding this method provides test coverage for situations where the organization context might not be available, which is important for comprehensive testing of the feature flag functionality.

app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/ce/TestComponentCE.java (2)

16-16: Interface method signature updated correctly.

The method signature change aligns with the implementation in TestComponentCEImpl and supports the PR's goal of using organization context for feature flags.


22-22: Good addition of method for organization-less scenarios.

Adding this method declaration supports testing edge cases where organization context might not be available.

app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourceTriggerSolutionCEImpl.java (2)

118-119: Good extraction of organization ID from request context.

Extracting the organization ID from the updated trigger request DTO is the right approach for maintaining organization context throughout the feature flag evaluation process.


130-136: Proper integration of feature flags with plugin execution.

The updated method call correctly passes the feature flag map to the plugin executor, ensuring that organization-specific flags are considered during execution.

app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java (1)

185-185: Duplicate concurrency concern.
This map mutation repeats the concurrency concern noted above. Ensure safe concurrent access or confirm that concurrency is not an issue in this context.

app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/TestComponentImpl.java (2)

43-44: Verify null handling for organizationId.
Ensure that calls to this method handle a potentially missing organizationId gracefully, or confirm that it's always non-null in this usage.


58-63: Double-check necessity of the no-organization variant.
Since @FeatureFlagged is tied to an organization context, confirm that skipping organizationId aligns with the intended design.

app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImpl.java (2)

41-41: Import looks good.
No concerns regarding the new import statement.


758-762: Confirm safe handling of empty user contexts.
getCurrentUser() might sometimes be empty. Ensure the subsequent usage of .getOrganizationId() won’t trigger a null pointer when no user is present.

app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspect.java (2)

70-82: Enforce organization context for non-reactive flagged methods

This adds a necessary check for non-reactive methods using @FeatureFlagged annotation, requiring an organizationId parameter. The implementation properly validates the organization ID and throws an appropriate exception when missing.


125-130: Updated feature flag check method to require organization context

The isFeatureFlagEnabled method signature has been updated to require an organization ID parameter, aligning with the organization-specific feature flag requirements.

app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java (4)

46-47: Updated mock setup for organization-specific feature flags

The test setup has been properly updated to use any() matcher when mocking the getCachedOrganizationFeatureFlags method, reflecting the signature change.


113-119: Updated test to include organization ID parameter

The test has been correctly modified to set up the expected behavior with a specific organization ID and pass that ID to the method under test.


123-124: Updated test case to include organization ID

The test case properly passes the organization ID parameter to align with the new method signature requirements.


149-166:

❓ Verification inconclusive

Added test for missing organization ID scenario

This new test verifies that an exception is properly thrown when a non-reactive method annotated with @FeatureFlagged is called without an organization ID. The assertion correctly validates both the exception type and the error message.


🏁 Script executed:

#!/bin/bash
# Check if TestComponent contains the ceEeSyncMethodWithoutOrganization method that's being tested

fd -e java "TestComponent.java" -x cat {} | grep -A 5 "ceEeSyncMethodWithoutOrganization"

Length of output: 89


Please verify that the ceEeSyncMethodWithoutOrganization method is present in the implementation of TestComponent.

  • The search command for the method in TestComponent.java did not return any output. Please manually confirm whether the method is implemented under a different file name or has been relocated.
  • The new test in FeatureFlaggedMethodInvokerAspectTest.java appears correctly written—it checks that invoking a non-reactive @FeatureFlagged method without an organization ID throws the expected exception with the proper error message.
  • Once you confirm that the ceEeSyncMethodWithoutOrganization method exists (or adjust its location accordingly), this test will effectively validate the missing organization ID scenario.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ok-to-test Required label for CI skip-changelog Adding this label to a PR prevents it from being listed in the changelog
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants