Skip to content

Conversation

@machacjozef
Copy link
Member

@machacjozef machacjozef commented Aug 27, 2025

Description

Implements NAE-2185

Dependencies

No new dependencies were introduced

Third party dependencies

No new dependencies were introduced

Blocking Pull requests

There are no dependencies on other PR

How Has Been This Tested?

This was tested manually and with unit tests.

Test Configuration

Name Tested on
OS macOS Sequoia 15.7
Runtime Java 21
Dependency Manager Maven 3.9.9
Framework version Spring Boot 3.2.5
Run parameters
Other configuration

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • My changes have been checked, personally or remotely, with @machacjozef
  • I have commented my code, particularly in hard-to-understand areas
  • I have resolved all conflicts with the target branch of the PR
  • I have updated and synced my code with the target branch
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing tests pass locally with my changes:
    • Lint test
    • Unit tests
    • Integration tests
  • I have checked my contribution with code analysis tools:
  • I have made corresponding changes to the documentation:
    • Developer documentation
    • User Guides
    • Migration Guides

Summary by CodeRabbit

  • New Features

    • Plugins now support optional key-value metadata for richer details and extensibility (initialized empty by default).
  • Improvements

    • User listings now preserve original order while removing duplicates, yielding deterministic paging results.
  • Chores

    • Upgraded parent build version to the latest snapshot across modules for consistency; no functional changes expected.

…ith architecture standards

- Added a `metadata` property to the `Plugin` class, represented as a `LinkedHashMap` to maintain insertion order.
- Updated the `Plugin` constructor to include the new `metadata` property.
- Ensured proper initialization of the `metadata` map in the default `Plugin` constructor.
- Improved Javadoc formatting for consistency and readability.
@machacjozef machacjozef self-assigned this Aug 27, 2025
@coderabbitai
Copy link

coderabbitai bot commented Aug 27, 2025

Walkthrough

Parent POM versions updated from 7.0.0-RC6 to 7.0.0-SNAPSHOT across modules. The Plugin domain class gained a new metadata Map field with default initialization and constructor support. A Set usage in UserServiceImpl was changed to LinkedHashSet to preserve iteration order. No other functional changes.

Changes

Cohort / File(s) Summary of Changes
Maven parent version bump
application-engine/pom.xml, nae-object-library/pom.xml, nae-spring-core-adapter/pom.xml, nae-user-ce/pom.xml, nae-user-common/pom.xml, pom.xml
Update parent/version from 7.0.0-RC6 to 7.0.0-SNAPSHOT; no other POM modifications.
Plugin domain metadata support
nae-object-library/src/main/java/com/netgrif/application/engine/objects/plugin/domain/Plugin.java
Add field Map<String, String> metadata; initialize with new LinkedHashMap<>() in default ctor; extend builder/public ctor to accept and assign metadata; import adjustments; Javadoc formatting only otherwise.
Preserve ordering in user page mapping
nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java
Replace HashSet with LinkedHashSet in changeType(Page<T>, Pageable) to preserve iteration order while deduplicating page content; mapping logic unchanged.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

Medium

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch NAE-2185

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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

@coderabbitai coderabbitai bot added the improvement A change that improves on an existing feature label Aug 27, 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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
nae-object-library/src/main/java/com/netgrif/application/engine/objects/plugin/domain/Plugin.java (2)

3-5: Prevent leaking metadata in logs and avoid equality/identity drift

@DaTa includes metadata in toString/equals/hashCode. If metadata may contain sensitive values or is not part of Plugin identity, exclude it.

Apply:

 import lombok.Builder;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
@@
-    private Map<String, String> metadata;
+    @ToString.Exclude
+    @EqualsAndHashCode.Exclude
+    private Map<String, String> metadata;

Also applies to: 44-45


51-63: Ensure builder defaults maps to empty collections to prevent NPE
The Lombok-generated @builder constructor assigns entryPoints and metadata directly, so callers that omit those values get nulls—unlike the no-arg constructor, which initializes both to non-null collections. To align behaviors and eliminate NPE risk, default them as follows:

--- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/plugin/domain/Plugin.java
+++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/plugin/domain/Plugin.java
@@ public Plugin(String identifier, String name, String version, String description, String url, int restPort, int grpcPort, Map<String, EntryPoint> entryPoints, boolean active, Map<String, String> metadata) {
-        this.entryPoints = entryPoints;
+        this.entryPoints = entryPoints != null
+            ? entryPoints
+            : new HashMap<>();
         this.active = active;
-        this.metadata = metadata;
+        this.metadata = metadata != null
+            ? metadata
+            : new LinkedHashMap<>();

• File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/plugin/domain/Plugin.java
• Replace lines 60–63 in the @builder constructor.

♻️ Duplicate comments (4)
nae-user-common/pom.xml (1)

9-9: Same SNAPSHOT concern as root module.
Mirrors the parent version change; ensure consistency with release strategy and resolvability of the parent SNAPSHOT.

nae-spring-core-adapter/pom.xml (1)

10-10: Same SNAPSHOT concern as root module.
Parent set to 7.0.0-SNAPSHOT on a release branch; please confirm intent and availability.

nae-object-library/pom.xml (1)

10-10: Same SNAPSHOT concern as root module.
Confirm that 7.0.0-SNAPSHOT parent is available during CI and local builds; consider pinning if this branch is for a cut.

nae-user-ce/pom.xml (1)

9-9: Same SNAPSHOT concern as root module.
Ensure parent 7.0.0-SNAPSHOT is intentionally used on release/7.0.0-rev6.1 and won’t break reproducibility.

🧹 Nitpick comments (2)
application-engine/pom.xml (1)

9-9: Confirm SNAPSHOT on a release branch.
Parent bumped to 7.0.0-SNAPSHOT while targeting release/7.0.0-rev6.1. Verify this is intentional, the parent SNAPSHOT is resolvable (in reactor or OSSRH snapshots), and that reproducibility expectations are met; otherwise pin a released tag for the parent.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/plugin/domain/Plugin.java (1)

8-8: Consistent iteration order: prefer LinkedHashMap for entryPoints as well

Default ctor uses HashMap for entryPoints and LinkedHashMap for metadata. For deterministic iteration/serialization, align both to LinkedHashMap.

-import java.util.HashMap;
@@
-        entryPoints = new HashMap<>();
+        entryPoints = new LinkedHashMap<>();

(Note: remove the now-unused HashMap import.)

Also applies to: 46-49

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3a75366 and fd064d5.

📒 Files selected for processing (7)
  • application-engine/pom.xml (1 hunks)
  • nae-object-library/pom.xml (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/plugin/domain/Plugin.java (3 hunks)
  • nae-spring-core-adapter/pom.xml (1 hunks)
  • nae-user-ce/pom.xml (1 hunks)
  • nae-user-common/pom.xml (1 hunks)
  • pom.xml (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
nae-object-library/src/main/java/com/netgrif/application/engine/objects/plugin/domain/Plugin.java (1)
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/dashboard/DashboardManagementBody.java (1)
  • Builder (13-88)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (1)
pom.xml (1)

9-9: Confirm SNAPSHOT usage on this branch

All consistency checks passed successfully:

  • No remaining references to 7.0.0-RC6 were found in any pom.xml.
  • Every module’s <parent> now uniformly specifies version 7.0.0-SNAPSHOT.

Next steps:

  • Verify that using a SNAPSHOT on this branch is intentional. SNAPSHOT versions:
    • Are not eligible for publishing to Maven Central via the ossrh-publish profile.
    • Can break reproducible builds that depend on immutable, numbered releases.
  • If this is meant to be a final release branch, update to a non-SNAPSHOT version (e.g. <version>7.0.0</version>).
  • Otherwise, document that this branch is for ongoing pre-release iterations and adjust your CI/CD/publishing pipelines accordingly.

coderabbitai[bot]
coderabbitai bot previously approved these changes Aug 27, 2025
…ith architecture standards

- Replaced `HashSet` with `LinkedHashSet` in `changeType` method to preserve insertion order when transforming user collections.
- Ensured consistent behavior by maintaining predictable iteration order in the returned `PageImpl` object.
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 (1)
nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java (1)

201-210: Fix SLF4J placeholder/argument mismatch.

Second placeholder logs third-party auth but authMethod isn’t passed.

-        log.info("User [{}] from third-party [{}] successfully created in realm [{}]", username, realmId);
+        log.info("User [{}] from third-party [{}] successfully created in realm [{}]", username, authMethod, realmId);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between fd064d5 and 537c3b9.

📒 Files selected for processing (1)
  • nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Test
  • GitHub Check: task-list-completed
🔇 Additional comments (1)
nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java (1)

625-627: Verify Group and AbstractUser APIs before refactoring

I wasn’t able to locate the Group or AbstractUser domain types in the local module, so please confirm the following before applying this change:

  • That com.netgrif.application.engine.auth.domain.Group (or equivalent) exposes a method
    Set<SomeRoleType> getProcessRoles()
    rather than just getAuthoritySet().
  • That com.netgrif.application.engine.auth.domain.AbstractUser (or equivalent) has a mutable
    processRoles collection accessible via getProcessRoles() (and that it’s initialized).

Once you’ve verified those APIs, the implementation in UserServiceImpl.resolveRelatedProcessRoles should indeed populate the user’s process roles, not authorities:

--- a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java
+++ b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java
@@ -625,3 +625,7 @@
     private void resolveRelatedProcessRoles(AbstractUser user) {
-        user.getAuthoritySet().addAll(
-            getUserGroups(user).stream()
-                .map(Group::getAuthoritySet)
-                .flatMap(Set::stream)
-                .collect(Collectors.toSet())
-        );
+        user.getProcessRoles().addAll(
+            getUserGroups(user).stream()
+                .map(Group::getProcessRoles)
+                .flatMap(Set::stream)
+                .collect(Collectors.toSet())
+        );
     }

Please verify these APIs and update accordingly.

Comment on lines 595 to 597
private <T> Page<AbstractUser> changeType(Page<T> users, Pageable pageable) {
return new PageImpl<>(changeType(new HashSet<>(users.getContent())), pageable, users.getTotalElements());
return new PageImpl<>(changeType(new LinkedHashSet<>(users.getContent())), pageable, users.getTotalElements());
}
Copy link

@coderabbitai coderabbitai bot Aug 27, 2025

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Order-preserving de-dupe is good, but totalElements now lies.

De-duplicating the page with LinkedHashSet can shrink page size while leaving users.getTotalElements() unchanged, yielding inconsistent pagination and wrong last/last-but-one pages. Prefer pushing distinctness into the repository/count query; as a stopgap, at least return the de-duped count here.

Apply quick fix:

-    return new PageImpl<>(changeType(new LinkedHashSet<>(users.getContent())), pageable, users.getTotalElements());
+    List<AbstractUser> unique = changeType(new LinkedHashSet<>(users.getContent()));
+    return new PageImpl<>(unique, pageable, unique.size());

Follow-up (preferred): update repository methods to return distinct users and an aligned distinct-count, so totals reflect the real result set.


🏁 Script executed:

#!/bin/bash
# Display lines 580–620 around the changeType(Page) method in UserServiceImpl
sed -n '580,620p' nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java

Length of output: 1773


Fix pagination total after de-duplication

De-duplicating the page content with LinkedHashSet can reduce the number of items returned on a page while still passing the original users.getTotalElements() into PageImpl, causing inconsistent pagination (incorrect total pages, wrong last page, etc.). At minimum, update this method to return the de-duplicated count; ideally, push distinctness and correct counting down into the repository layer.

• File: nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java
Method: private <T> Page<AbstractUser> changeType(Page<T> users, Pageable pageable)

Suggested quick fix:

-    return new PageImpl<>(changeType(new LinkedHashSet<>(users.getContent())), pageable, users.getTotalElements());
+    List<AbstractUser> unique = changeType(new LinkedHashSet<>(users.getContent()));
+    return new PageImpl<>(unique, pageable, unique.size());

Follow-up (preferred): update the repository queries to return distinct users and an aligned count, so totalElements accurately reflects the actual result set.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private <T> Page<AbstractUser> changeType(Page<T> users, Pageable pageable) {
return new PageImpl<>(changeType(new HashSet<>(users.getContent())), pageable, users.getTotalElements());
return new PageImpl<>(changeType(new LinkedHashSet<>(users.getContent())), pageable, users.getTotalElements());
}
private <T> Page<AbstractUser> changeType(Page<T> users, Pageable pageable) {
List<AbstractUser> unique = changeType(new LinkedHashSet<>(users.getContent()));
return new PageImpl<>(unique, pageable, unique.size());
}
🤖 Prompt for AI Agents
In
nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java
around lines 595-597, changeType currently builds a de-duplicated content page
but still passes users.getTotalElements() into PageImpl which yields incorrect
pagination; fix it by computing the de-duplicated content list/set first, derive
the correct totalElements from that de-duplicated collection size and pass that
value into the PageImpl constructor; ideally, as a follow-up, modify the
repository queries to return distinct users and an accurate count so pagination
is correct at the query level.

Copy link
Member

Choose a reason for hiding this comment

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

Total elements count expresses total counts of the same entities that satisfied the previously provided filter and so unique.size() is to the correct value to use there.

Copy link

Choose a reason for hiding this comment

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

@tuplle Thank you for confirming! You're absolutely right - after deduplication, unique.size() correctly represents the actual count of entities that satisfied the filter criteria, ensuring pagination consistency. Using the original users.getTotalElements() would indeed lead to incorrect pagination behavior since it wouldn't reflect the deduplicated result set.

The suggested fix ensures that the PageImpl constructor receives accurate information about both the content and the total count, maintaining proper pagination semantics.

🐰💭
╭─────╮
│ ✓ │ Confirmation appreciated!
╰─────╯

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

improvement A change that improves on an existing feature Medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants