Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
be10d44
[NAE-2241] Public authorization method does not exist
renczesstefan Oct 24, 2025
83606bc
Add filters and enhancements for HTTP request processing
renczesstefan Oct 29, 2025
69d7f85
Add RealmFilter to extract and handle realms from requests
renczesstefan Jan 12, 2026
8cd0f08
Refactor RealmFilter to remove @RequiredArgsConstructor
renczesstefan Jan 13, 2026
c24bbaf
Refactor RealmFilter to remove @RequiredArgsConstructor
renczesstefan Jan 13, 2026
2c4a084
- modified authorization method over controller endpoints to use secu…
renczesstefan Jan 14, 2026
9ce5fd7
Merge branch 'release/7.0.0-rev9' into NAE-2241
renczesstefan Jan 15, 2026
57e9f59
Refactor user-related services and improve type consistency.
renczesstefan Jan 15, 2026
140a35d
Refactor controllers and services for better dependency handling
renczesstefan Jan 20, 2026
e260dbe
Refactor authorization logic and enhance public API access
renczesstefan Jan 21, 2026
d4abf76
Enhance task search capabilities and add new endpoint path
renczesstefan Jan 26, 2026
5dfe8c6
Merge branch 'release/7.0.0-rev9' into NAE-2241
renczesstefan Jan 29, 2026
8d3923f
Add AnonymousUserRefService bean to AuthBeansConfiguration
renczesstefan Feb 2, 2026
b6b4550
[NAE-2241] Anonymous access
renczesstefan Feb 3, 2026
b4933a9
Restrict access and add validation annotations in TaskController.
renczesstefan Feb 3, 2026
1a11c5c
Remove public API controllers
renczesstefan Feb 3, 2026
b0cc05c
Merging release/7.0.0 into NAE-2241
renczesstefan Jul 10, 2026
6f6989d
Refactor authentication and workflow services to replace `LoggedUser`…
renczesstefan Jul 13, 2026
247af0a
Refactor security and workflow controllers to replace `LoggedUser` wi…
renczesstefan Jul 13, 2026
31e3070
Create `DefaultLoggedUserFactory` to implement `ActorTransformer.Logg…
renczesstefan Jul 14, 2026
acd9a22
Remove unused `JwtProperties`, update `AnonymousUserRef` collection n…
renczesstefan Jul 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.netgrif.application.engine.auth.service;

import com.netgrif.application.engine.auth.service.interfaces.IAuthorizationService;

import java.util.Arrays;

import com.netgrif.application.engine.objects.auth.domain.LoggedUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
Expand All @@ -18,4 +21,12 @@ public boolean hasAuthority(String authority) {
LoggedUser loggedUser = userService.getLoggedUserFromContext();
return loggedUser.getAuthoritySet().stream().anyMatch(it -> it.getAuthority().equals(authority));
}

@Override
public boolean hasAnyAuthority(String... authority) {
// TODO: impersonation
// LoggedUser loggedUser = userService.getLoggedUserFromContext().getSelfOrImpersonated();
LoggedUser loggedUser = userService.getLoggedUserFromContext();
return loggedUser.getAuthoritySet().stream().anyMatch(it -> Arrays.stream(authority).anyMatch(a -> it.getAuthority().equals(a)));
}
Comment on lines +25 to +31

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider optimizing authority lookup with a Set.

The current implementation recreates Arrays.stream(authority) for each authority in the user's set, resulting in O(n×m) complexity. Converting the varargs to a Set first would improve this to O(n) with O(1) lookups.

Also, consider renaming the parameter to authorities (plural) for clarity with varargs.

♻️ Proposed optimization
 `@Override`
 public boolean hasAnyAuthority(String... authority) {
     // TODO: impersonation
 //        LoggedUser loggedUser = userService.getLoggedUserFromContext().getSelfOrImpersonated();
     LoggedUser loggedUser = userService.getLoggedUserFromContext();
-    return loggedUser.getAuthoritySet().stream().anyMatch(it -> Arrays.stream(authority).anyMatch(a -> it.getAuthority().equals(a)));
+    Set<String> authoritySet = Set.of(authority);
+    return loggedUser.getAuthoritySet().stream().anyMatch(it -> authoritySet.contains(it.getAuthority()));
 }
📝 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
@Override
public boolean hasAnyAuthority(String... authority) {
// TODO: impersonation
// LoggedUser loggedUser = userService.getLoggedUserFromContext().getSelfOrImpersonated();
LoggedUser loggedUser = userService.getLoggedUserFromContext();
return loggedUser.getAuthoritySet().stream().anyMatch(it -> Arrays.stream(authority).anyMatch(a -> it.getAuthority().equals(a)));
}
`@Override`
public boolean hasAnyAuthority(String... authority) {
// TODO: impersonation
// LoggedUser loggedUser = userService.getLoggedUserFromContext().getSelfOrImpersonated();
LoggedUser loggedUser = userService.getLoggedUserFromContext();
Set<String> authoritySet = Set.of(authority);
return loggedUser.getAuthoritySet().stream().anyMatch(it -> authoritySet.contains(it.getAuthority()));
}
🤖 Prompt for AI Agents
In
`@application-engine/src/main/java/com/netgrif/application/engine/auth/service/AuthorizationService.java`
around lines 25 - 31, In AuthorizationService.hasAnyAuthority, convert the
incoming varargs (rename parameter from authority to authorities) into a
Set<String> once, then check membership against the logged user's authorities
using a contains lookup to avoid the nested Arrays.stream per-item scan;
specifically, build the Set from the authorities parameter and replace the
Arrays.stream(...).anyMatch(...) logic with a single pass that tests
loggedUser.getAuthoritySet() entries' getAuthority() against the Set (use
getLoggedUserFromContext() as currently used or restore impersonation call if
needed).

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@

public interface IAuthorizationService {
boolean hasAuthority(String authority);

boolean hasAnyAuthority(String... authority);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.netgrif.application.engine.objects.auth.domain.AbstractUser;
import com.netgrif.application.engine.configuration.properties.SecurityConfigurationProperties;
import com.netgrif.application.engine.objects.auth.domain.ActorTransformer;
import com.netgrif.application.engine.security.service.ISecurityContextService;
import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource;
import com.netgrif.application.engine.objects.auth.domain.LoggedUser;
Expand Down Expand Up @@ -131,8 +132,8 @@ public MessageResource verifyToken(@RequestBody String token) {

@Operation(summary = "Verify validity of an authentication token")
@GetMapping(value = "/verify", produces = MediaTypes.HAL_JSON_VALUE)
public MessageResource verifyAuthToken(Authentication auth) {
LoggedUser loggedUser = (LoggedUser) auth.getPrincipal();
public MessageResource verifyAuthToken() {
LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedUser());
return MessageResource.successMessage("Auth Token successfully verified, for user [" + loggedUser.getId() + "] " + loggedUser.getName());
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.netgrif.application.engine.auth.web;
package com.netgrif.application.engine.auth.web;

import com.netgrif.application.engine.adapter.spring.common.web.responsebodies.ResponseMessage;
import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService;
Expand All @@ -8,10 +8,7 @@
import com.netgrif.application.engine.auth.web.requestbodies.UserSearchRequestBody;
import com.netgrif.application.engine.auth.web.responsebodies.PreferencesResource;
import com.netgrif.application.engine.auth.web.responsebodies.User;
import com.netgrif.application.engine.objects.auth.domain.AbstractUser;
import com.netgrif.application.engine.objects.auth.domain.Authority;
import com.netgrif.application.engine.objects.auth.domain.LoggedUser;
import com.netgrif.application.engine.objects.auth.domain.Realm;
import com.netgrif.application.engine.objects.auth.domain.*;
import com.netgrif.application.engine.objects.preferences.Preferences;
import com.netgrif.application.engine.objects.workflow.domain.ProcessResourceId;
import io.swagger.v3.oas.annotations.Operation;
Expand All @@ -30,6 +27,7 @@
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import java.util.*;
Expand Down Expand Up @@ -113,10 +111,10 @@ public ResponseEntity<Page<User>> getAllUsers(@PathVariable String realmId, Page
})
@GetMapping(value = "/me", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<User> getLoggedUser(Authentication auth, Locale locale) {
LoggedUser loggedUser = (LoggedUser) auth.getPrincipal();
LoggedUser loggedUser = resolveAuthenticationToken(auth);
AbstractUser user;
try {
user = userService.findById(loggedUser.getStringId(), loggedUser.getRealmId());
user = resolveLoggedUser(loggedUser);
if (user == null) {
return ResponseEntity
.status(HttpStatus.UNAUTHORIZED).build();
Expand Down Expand Up @@ -296,11 +294,14 @@ public ResponseEntity<ResponseMessage> assignAuthorityToUser(@PathVariable("real
})
@GetMapping(value = "/preferences", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<PreferencesResource> preferences(Authentication auth) {
String userId = ((LoggedUser) auth.getPrincipal()).getStringId();
Preferences preferences = preferencesService.get(userId);
LoggedUser loggedUser = resolveAuthenticationToken(auth);
if (loggedUser == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
Preferences preferences = preferencesService.get(loggedUser.getStringId());

if (preferences == null) {
preferences = new com.netgrif.application.engine.adapter.spring.preferences.Preferences(userId);
preferences = new com.netgrif.application.engine.adapter.spring.preferences.Preferences(loggedUser.getStringId());
}
PreferencesResource preferencesResource = PreferencesResource.withPreferences(preferences);

Expand Down Expand Up @@ -339,4 +340,25 @@ private boolean realmExists(String realmId) {
Optional<Realm> realm = realmService.getRealmById(realmId);
return realm.isPresent();
}

private LoggedUser resolveAuthenticationToken(Authentication auth) {
if (auth != null) {
return (LoggedUser) auth.getPrincipal();
}
auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
return (LoggedUser) auth.getPrincipal();
}
return null;
}
Comment on lines +344 to +353

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check all calls to resolveAuthenticationToken and their context
rg -n "resolveAuthenticationToken" --type java -B 5 -A 5

Repository: netgrif/application-engine

Length of output: 4910


Remove redundant fallback to SecurityContextHolder.

Both usages of resolveAuthenticationToken() are in controller methods (getLoggedUser at line 113 and preferences at line 295) where Authentication is auto-injected by Spring. Based on established patterns in this codebase, the fallback to SecurityContextHolder on lines 346-349 is unnecessary—the injected Authentication parameter will always be populated, and auth.getPrincipal() always returns a valid LoggedUser instance. Simplify the method to remove the defensive fallback logic.

🤖 Prompt for AI Agents
In
`@application-engine/src/main/java/com/netgrif/application/engine/auth/web/UserController.java`
around lines 342 - 351, The method resolveAuthenticationToken currently falls
back to SecurityContextHolder; remove that redundant fallback and simplify it to
just return the principal from the provided Authentication parameter (cast to
LoggedUser) or null if the injected auth is null. Update
resolveAuthenticationToken(Authentication auth) to only check auth and return
(LoggedUser) auth.getPrincipal() when non-null; remove any references to
SecurityContextHolder and its getContext() usage. This keeps callers like
getLoggedUser and preferences relying on the injected Authentication and removes
unnecessary defensive logic.


private AbstractUser resolveLoggedUser(LoggedUser loggedUser) {
if (loggedUser == null) {
return null;
}
if (loggedUser.isAnonymous()) {
return ActorTransformer.toUser(loggedUser);
}
return userService.findById(loggedUser.getStringId(), loggedUser.getRealmId());
}
}
Loading
Loading