|
26 | 26 | import org.pentaho.platform.engine.security.authorization.core.decisions.DefaultAuthorizationDecision; |
27 | 27 | import org.pentaho.platform.engine.security.authorization.core.exceptions.AuthorizationRequestCycleException; |
28 | 28 | import org.pentaho.platform.engine.security.authorization.core.exceptions.AuthorizationRequestUndefinedActionException; |
| 29 | +import org.pentaho.platform.engine.security.authorization.core.rules.AbstractAuthorizationRule; |
29 | 30 | import org.springframework.util.Assert; |
30 | 31 |
|
31 | 32 | import java.util.ArrayDeque; |
32 | 33 | import java.util.Deque; |
33 | 34 | import java.util.Objects; |
34 | 35 | import java.util.Optional; |
35 | 36 |
|
| 37 | +/** |
| 38 | + * The {@code AuthorizationService} class is the default implementation of the {@link IAuthorizationService} interface. |
| 39 | + * <p> |
| 40 | + * It performs authorization evaluations based on a root authorization rule, which may delegate to other rules as |
| 41 | + * needed. |
| 42 | + * <p> |
| 43 | + * The implementation is thread-safe, as each authorization evaluation is performed within its own |
| 44 | + * {@link AuthorizationContext}, which tracks the evaluation state for that specific request. |
| 45 | + * Of course, the thread-safety of the overall service also depends on the thread-safety of the provided authorization |
| 46 | + * rules. |
| 47 | + * <p> |
| 48 | + * One exception is setting the root rule, using {@link #setRootRule(IAuthorizationRule)} which is not thread-safe. Care |
| 49 | + * must be taken to avoid inconsistent decisions in concurrent evaluations. This is intended to be used during |
| 50 | + * application initialization. |
| 51 | + */ |
36 | 52 | public class AuthorizationService implements IAuthorizationService { |
37 | 53 |
|
38 | 54 | private static final Log logger = LogFactory.getLog( AuthorizationService.class ); |
@@ -207,17 +223,45 @@ protected IAuthorizationDecision getDefaultDecision( @NonNull IAuthorizationRequ |
207 | 223 | } |
208 | 224 | } |
209 | 225 |
|
| 226 | + /** |
| 227 | + * An authorization rule that always abstains. Used as a default root rule if none is provided. |
| 228 | + */ |
| 229 | + private static class AbstainAuthorizationRule extends AbstractAuthorizationRule<IAuthorizationRequest> { |
| 230 | + |
| 231 | + @NonNull |
| 232 | + @Override |
| 233 | + public Class<IAuthorizationRequest> getRequestType() { |
| 234 | + return IAuthorizationRequest.class; |
| 235 | + } |
| 236 | + |
| 237 | + @NonNull |
| 238 | + @Override |
| 239 | + public Optional<IAuthorizationDecision> authorize( @NonNull IAuthorizationRequest request, |
| 240 | + @NonNull IAuthorizationContext context ) { |
| 241 | + return abstain(); |
| 242 | + } |
| 243 | + } |
| 244 | + |
210 | 245 | @NonNull |
211 | 246 | private final IAuthorizationActionService actionService; |
212 | 247 |
|
213 | 248 | @NonNull |
214 | | - private final IAuthorizationRule<? extends IAuthorizationRequest> rootRule; |
| 249 | + private IAuthorizationRule<? extends IAuthorizationRequest> rootRule; |
| 250 | + |
| 251 | + /** |
| 252 | + * Constructs an instance of the authorization service with a default root rule that always abstains. |
| 253 | + * |
| 254 | + * @param actionService The service providing access to authorization actions. |
| 255 | + */ |
| 256 | + public AuthorizationService( @NonNull IAuthorizationActionService actionService ) { |
| 257 | + this( actionService, new AbstainAuthorizationRule() ); |
| 258 | + } |
215 | 259 |
|
216 | 260 | /** |
217 | 261 | * Constructs an instance of the authorization service with a given root rule. |
218 | 262 | * |
219 | 263 | * @param actionService The service providing access to authorization actions. |
220 | | - * @param rootRule The root authorization rule. |
| 264 | + * @param rootRule The root authorization rule. |
221 | 265 | */ |
222 | 266 | public AuthorizationService( @NonNull IAuthorizationActionService actionService, |
223 | 267 | @NonNull IAuthorizationRule<? extends IAuthorizationRequest> rootRule ) { |
@@ -263,17 +307,30 @@ protected AuthorizationContext createContext( @NonNull IAuthorizationOptions opt |
263 | 307 | * @return The root rule. |
264 | 308 | */ |
265 | 309 | @NonNull |
266 | | - protected final IAuthorizationRule<? extends IAuthorizationRequest> getRootRule() { |
| 310 | + public final IAuthorizationRule<? extends IAuthorizationRequest> getRootRule() { |
267 | 311 | return rootRule; |
268 | 312 | } |
269 | 313 |
|
| 314 | + /** |
| 315 | + * Sets the root authorization rule. |
| 316 | + * <p> |
| 317 | + * Warning: changing the root rule at runtime may lead to inconsistent authorization decisions if there are |
| 318 | + * concurrent authorization evaluations. This method should only be used during application initialization. |
| 319 | + * |
| 320 | + * @param rootRule The root rule. |
| 321 | + */ |
| 322 | + public final void setRootRule( @NonNull IAuthorizationRule<? extends IAuthorizationRequest> rootRule ) { |
| 323 | + Assert.notNull( rootRule, "Argument 'rootRule' is required" ); |
| 324 | + this.rootRule = rootRule; |
| 325 | + } |
| 326 | + |
270 | 327 | /** |
271 | 328 | * Gets the authorization action service. |
272 | 329 | * |
273 | 330 | * @return The action service. |
274 | 331 | */ |
275 | 332 | @NonNull |
276 | | - protected IAuthorizationActionService getActionService() { |
| 333 | + protected final IAuthorizationActionService getActionService() { |
277 | 334 | return actionService; |
278 | 335 | } |
279 | 336 | } |
0 commit comments