Skip to content

Commit ab4b448

Browse files
committed
📝 Add comprehensive JavaDoc to org.restheart.polyglot and org.restheart.security packages of module commons
1 parent d2c1954 commit ab4b448

13 files changed

+1626
-169
lines changed

commons/src/main/java/org/restheart/polyglot/NodeQueue.java

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,69 @@
2222
import java.util.Queue;
2323
import java.util.concurrent.LinkedBlockingDeque;
2424

25+
/**
26+
* A singleton queue implementation for communication between RESTHeart and Node.js polyglot environments.
27+
*
28+
* <p>This class provides a thread-safe, blocking queue that facilitates data exchange between
29+
* the Java-based RESTHeart server and JavaScript code running in a Node.js environment via
30+
* GraalVM's polyglot capabilities.</p>
31+
*
32+
* <p>The queue is implemented as a singleton to ensure a single shared communication channel
33+
* across the entire application. It uses a {@link LinkedBlockingDeque} internally to provide
34+
* thread-safe operations without explicit synchronization.</p>
35+
*
36+
* <p>Example usage:</p>
37+
* <pre>{@code
38+
* // Get the singleton instance
39+
* NodeQueue queue = NodeQueue.instance();
40+
*
41+
* // Add data to the queue
42+
* queue.queue().offer(someData);
43+
*
44+
* // Check if running in Node.js context
45+
* if (queue.isRunningOnNode()) {
46+
* // Perform Node.js specific operations
47+
* }
48+
* }</pre>
49+
*
50+
* @author Andrea Di Cesare {@literal <andrea@softinstigate.com>}
51+
* @since 8.0.0
52+
*/
2553
public class NodeQueue {
26-
// a concurrent queue shared with Node
54+
/**
55+
* The concurrent queue used for communication with Node.js.
56+
* This queue can safely be accessed from multiple threads.
57+
*/
2758
private final Queue<Object> queue;
59+
60+
/**
61+
* Flag indicating whether the current execution context is within a Node.js environment.
62+
* This is set to true when RESTHeart is running with Node.js polyglot support enabled.
63+
*/
2864
private boolean runningOnNode = false;
2965

66+
/**
67+
* Private constructor to enforce singleton pattern.
68+
* Initializes the internal queue with a thread-safe {@link LinkedBlockingDeque}.
69+
*/
3070
private NodeQueue() {
3171
this.queue = new LinkedBlockingDeque<>();
3272
}
3373

74+
/**
75+
* The singleton instance of NodeQueue.
76+
*/
3477
private static NodeQueue instance;
3578

79+
/**
80+
* Returns the singleton instance of NodeQueue.
81+
*
82+
* <p>This method lazily initializes the queue on first access. While not strictly
83+
* thread-safe, the race condition is benign as multiple threads creating instances
84+
* would create functionally identical objects, and only one would ultimately be used.</p>
85+
*
86+
* @return the singleton NodeQueue instance
87+
*/
3688
public static NodeQueue instance() {
3789
if (instance == null) {
3890
instance = new NodeQueue();
@@ -41,14 +93,44 @@ public static NodeQueue instance() {
4193
return instance;
4294
}
4395

96+
/**
97+
* Returns the underlying queue for direct manipulation.
98+
*
99+
* <p>The returned queue is thread-safe and supports all standard {@link Queue} operations.
100+
* Common operations include:</p>
101+
* <ul>
102+
* <li>{@code offer(Object)} - adds an element to the queue</li>
103+
* <li>{@code poll()} - retrieves and removes the head element, or returns null if empty</li>
104+
* <li>{@code peek()} - retrieves but does not remove the head element</li>
105+
* </ul>
106+
*
107+
* @return the concurrent queue instance
108+
*/
44109
public Queue<Object> queue() {
45110
return queue;
46111
}
47112

113+
/**
114+
* Checks whether the current execution context is within a Node.js environment.
115+
*
116+
* <p>This method is typically used to conditionally execute code based on whether
117+
* RESTHeart is running with Node.js polyglot support enabled.</p>
118+
*
119+
* @return {@code true} if running in a Node.js context, {@code false} otherwise
120+
*/
48121
public boolean isRunningOnNode() {
49122
return runningOnNode;
50123
}
51124

125+
/**
126+
* Marks this instance as running within a Node.js environment.
127+
*
128+
* <p>This method should only be called by the polyglot initialization code when
129+
* setting up the Node.js execution context. Once set, this flag cannot be unset.</p>
130+
*
131+
* <p><strong>Note:</strong> This method is not thread-safe and should only be called
132+
* during application initialization.</p>
133+
*/
52134
public void setAsRunningOnNode() {
53135
this.runningOnNode = true;
54136
}

commons/src/main/java/org/restheart/security/ACLRegistry.java

Lines changed: 106 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -26,62 +26,139 @@
2626
/**
2727
* Registry for defining Access Control Lists (ACLs) programmatically.
2828
*
29-
* This registry is utilized by the {@code ACLRegistryVetoer} and {@code ACLRegistryAllower} authorizers
30-
* to manage request permissions. The {@code ACLRegistryVetoer} denies requests based on veto predicates,
31-
* while the {@code ACLRegistryAllower} grants permission to proceed with requests based on allow predicate.
29+
* <p>This registry serves as a central repository for dynamic access control rules that can be
30+
* registered at runtime. It is utilized by the {@code ACLRegistryVetoer} and {@code ACLRegistryAllower}
31+
* authorizers to manage request permissions in a flexible, programmatic manner.</p>
3232
*
33-
* A request is permitted to proceed if it is not denied by any {@code ACLRegistryVetoer} and at least one
34-
* {@code ACLRegistryAllower} approves it.
33+
* <h2>Authorization Model</h2>
34+
* <p>The registry implements a two-phase authorization model:</p>
35+
* <ol>
36+
* <li><strong>Veto Phase:</strong> The {@code ACLRegistryVetoer} evaluates all registered veto
37+
* predicates. If any predicate returns {@code true}, the request is immediately denied.</li>
38+
* <li><strong>Allow Phase:</strong> If not vetoed, the {@code ACLRegistryAllower} checks if at
39+
* least one allow predicate returns {@code true}. The request proceeds only if approved.</li>
40+
* </ol>
3541
*
36-
* Example usage:
37-
* <pre>
38-
* {@code
42+
* <p>A request is permitted to proceed if and only if:</p>
43+
* <ul>
44+
* <li>It is not denied by any {@code ACLRegistryVetoer} predicates, AND</li>
45+
* <li>At least one {@code ACLRegistryAllower} predicate approves it</li>
46+
* </ul>
47+
*
48+
* <h2>Example Usage</h2>
49+
* <pre>{@code
3950
* @Inject("acl-registry")
4051
* ACLRegistry registry;
4152
*
4253
* @OnInit
4354
* public void init() {
44-
* registry.registerVeto(request -> request.getPath().equals("/deny"));
45-
* registry.registerAllow(request -> request.getPath().equals("/allow"));
46-
* }
55+
* // Deny all requests to /admin from non-admin users
56+
* registry.registerVeto(request ->
57+
* request.getPath().startsWith("/admin") &&
58+
* !request.isAccountInRole("admin")
59+
* );
60+
*
61+
* // Allow authenticated users to access /api
62+
* registry.registerAllow(request ->
63+
* request.getPath().startsWith("/api") &&
64+
* request.isAuthenticated()
65+
* );
66+
*
67+
* // Require authentication for all /secure paths
68+
* registry.registerAuthenticationRequirement(request ->
69+
* request.getPath().startsWith("/secure")
70+
* );
4771
* }
48-
* </pre>
72+
* }</pre>
4973
*
5074
* @author Andrea Di Cesare {@literal <andrea@softinstigate.com>}
75+
* @since 6.0.0
76+
* @see org.restheart.security.plugins.authorizers.ACLRegistryVetoer
77+
* @see org.restheart.security.plugins.authorizers.ACLRegistryAllower
5178
*/
5279
public interface ACLRegistry {
5380
/**
5481
* Registers a veto predicate that determines if a request should be denied.
55-
* When the predicate evaluates to true, the request is immediately forbidden (vetoed).
56-
* Additionally, a request will also be denied if it is not explicitly authorized by any
57-
* allow predicates or any other active allowing authorizers.
82+
*
83+
* <p>When the predicate evaluates to {@code true}, the request is immediately forbidden (vetoed)
84+
* with no further evaluation. This provides a mechanism for implementing hard denials that cannot
85+
* be overridden by allow rules.</p>
86+
*
87+
* <p>Common use cases for veto predicates include:</p>
88+
* <ul>
89+
* <li>Blocking access to sensitive administrative endpoints</li>
90+
* <li>Enforcing IP-based access restrictions</li>
91+
* <li>Preventing access during maintenance windows</li>
92+
* <li>Implementing rate limiting or abuse prevention</li>
93+
* </ul>
94+
*
95+
* <p><strong>Note:</strong> Veto predicates are evaluated before allow predicates. A single
96+
* veto is sufficient to deny a request, regardless of any allow rules.</p>
5897
*
59-
* @param veto The veto predicate to register. This predicate should return true to veto (deny) the request,
60-
* and false to let the decision be further evaluated by allow predicates or other authorizers.
98+
* @param veto The veto predicate to register. This predicate should return {@code true} to veto
99+
* (deny) the request, and {@code false} to let the decision be further evaluated
100+
* by allow predicates or other authorizers
101+
* @throws NullPointerException if the veto predicate is null
61102
*/
62103
public void registerVeto(Predicate<Request<?>> veto);
63104

64105
/**
65106
* Registers an allow predicate that determines if a request should be authorized.
66-
* The request is authorized if this predicate evaluates to true, provided that no veto predicates
67-
* or other active vetoer authorizers subsequently deny the request. This method helps in setting up
68-
* conditions under which requests can proceed unless explicitly vetoed.
107+
*
108+
* <p>The request is authorized if this predicate evaluates to {@code true}, provided that no
109+
* veto predicates or other active vetoer authorizers have denied the request. Multiple allow
110+
* predicates can be registered, and the request proceeds if any one of them returns {@code true}.</p>
111+
*
112+
* <p>Common use cases for allow predicates include:</p>
113+
* <ul>
114+
* <li>Granting access based on user roles or permissions</li>
115+
* <li>Implementing path-based access control</li>
116+
* <li>Allowing access based on request headers or parameters</li>
117+
* <li>Implementing custom business logic for authorization</li>
118+
* </ul>
119+
*
120+
* <p><strong>Important:</strong> Allow predicates are only evaluated if no veto predicates
121+
* have denied the request. At least one allow predicate must return {@code true} for the
122+
* request to be authorized.</p>
69123
*
70-
* @param allow The allow predicate to register. This predicate should return true to authorize the request,
71-
* unless it is vetoed by any veto predicates or other vetoing conditions.
124+
* @param allow The allow predicate to register. This predicate should return {@code true} to
125+
* authorize the request, unless it is vetoed by any veto predicates or other
126+
* vetoing conditions
127+
* @throws NullPointerException if the allow predicate is null
72128
*/
73129
public void registerAllow(Predicate<Request<?>> allow);
74130

75131
/**
76-
* Registers a predicate that determines whether requests handled by the ACLRegistryAllower
77-
* require authentication. This method is used to specify conditions under which authentication
78-
* is mandatory. Typically, authentication is required unless there are allow predicates
79-
* explicitly authorizing requests that are not authenticated.
80-
*
132+
* Registers a predicate that determines whether requests require authentication.
133+
*
134+
* <p>This method is used to specify conditions under which authentication is mandatory before
135+
* authorization rules are evaluated. When the predicate returns {@code true}, the request must
136+
* have valid authentication credentials; otherwise, it will be rejected with a 401 Unauthorized
137+
* status.</p>
138+
*
139+
* <p>Authentication requirements are evaluated before authorization rules. This ensures that
140+
* sensitive endpoints can enforce authentication regardless of allow predicates.</p>
141+
*
142+
* <p>Common use cases include:</p>
143+
* <ul>
144+
* <li>Requiring authentication for all API endpoints</li>
145+
* <li>Enforcing authentication for specific URL patterns</li>
146+
* <li>Making authentication mandatory for certain HTTP methods</li>
147+
* <li>Implementing mixed authentication models (some paths public, others protected)</li>
148+
* </ul>
149+
*
150+
* <p>Example:</p>
151+
* <pre>{@code
152+
* // Require authentication for all paths except /public
153+
* registry.registerAuthenticationRequirement(request ->
154+
* !request.getPath().startsWith("/public")
155+
* );
156+
* }</pre>
81157
*
82158
* @param authenticationRequired The predicate to determine if authentication is necessary.
83-
* It should return true if the request must be authenticated,
84-
* otherwise false if unauthenticated requests might be allowed.
159+
* It should return {@code true} if the request must be authenticated,
160+
* otherwise {@code false} if unauthenticated requests might be allowed
161+
* @throws NullPointerException if the authenticationRequired predicate is null
85162
*/
86163
public void registerAuthenticationRequirement(Predicate<Request<?>> authenticationRequired);
87164

0 commit comments

Comments
 (0)