flyrain commented on code in PR #4409:
URL: https://github.com/apache/polaris/pull/4409#discussion_r3270508104


##########
polaris-core/src/main/java/org/apache/polaris/core/auth/AuthorizationIntent.java:
##########
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.core.auth;
+
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import org.apache.polaris.core.entity.PolarisEntityType;
+
+/** Authorization intent describing an operation and its target resource 
shape. */
+public sealed interface AuthorizationIntent
+    permits TargetlessAuthorizationIntent,
+        SingleTargetAuthorizationIntent,
+        PairwiseTargetAuthorizationIntent {
+  static AuthorizationIntent of(@Nonnull PolarisAuthorizableOperation 
operation) {
+    return new TargetlessAuthorizationIntent(operation);
+  }
+
+  static AuthorizationIntent of(
+      @Nonnull PolarisAuthorizableOperation operation, @Nonnull 
PolarisSecurable target) {
+    return new SingleTargetAuthorizationIntent(operation, target);
+  }
+
+  static AuthorizationIntent of(
+      @Nonnull PolarisAuthorizableOperation operation,
+      @Nullable PolarisSecurable target,
+      @Nullable PolarisSecurable secondary) {
+    return new PairwiseTargetAuthorizationIntent(operation, target, secondary);
+  }
+
+  @Nonnull
+  PolarisAuthorizableOperation getOperation();
+
+  @Nullable
+  PolarisSecurable getTarget();

Review Comment:
   Thanks for the change. I think `AuthorizationIntent` as a sealed hierarchy 
is the right shape for these requests. Want to flag something about the parent 
interface, because I don't think we're actually getting the benefit of sealing 
it.
   
   The parent exposes `@Nullable getTarget()` and `@Nullable getSecondary()`, 
plus `hasSecurableType` and `containsType`. Both callers, OPA's `authorize` and 
`PolarisAuthorizerImpl.authorizeIntent`, just pull the nullable accessors off 
and null-check at runtime; neither switches on the subtype. And 
`hasSecurableType` / `containsType` aren't called from anywhere in production 
code, only by their own tests. So we've ended up with three records, three 
factory overloads, two nullable parent accessors, and two unused helpers, but 
the ergonomic at the call site is identical to what 
`AuthorizationTargetBinding` gave us: a thing with two nullables, check them.
   
   What worries me more is what happens next. Say six months from now we add a 
`TripleTargetAuthorizationIntent(op, t1, t2, t3)`, merge-style ops eventually 
want something like that. With the current shape we'd either have to bolt 
`getTertiary()` onto the parent (every existing variant returns `null` for it, 
every caller grows another nullable branch) or pretend `t3` fits inside one of 
the accessors we already have. The parent interface ends up accumulating one 
nullable accessor per shape we've ever supported, and the seal stops paying its 
way entirely.
   
   I think the seal earns its keep if we make the parent thin, just 
`operation()`, and push typed access onto the subtypes:
   
   ```java
   switch (intent) {
     case TargetlessAuthorizationIntent t -> ...
     case SingleTargetAuthorizationIntent s -> ... s.target() ...        // 
@Nonnull
     case PairwiseTargetAuthorizationIntent p -> ... p.target(), p.secondary() 
...
   }
   ```
   
   Then `SingleTarget.target()` is non-null by type, so callers stop 
null-checking what the seal already guarantees. The 3-arg `of(op, target, 
secondary)` ambiguity quietly dissolves, no nullable parent contract to 
satisfy, no reason to overload. Adding `TripleTarget` later becomes a compile 
error at every switch site, which is exactly the property sealed types are 
there to give you. I'd suggest to push down the subtype switch as much as 
possible. If some methods are not ready for the change(e.g., the old method 
`authorizeOrThrow` still takes targets and secondaries, I'm OK to change it as 
a followup. 
   
   WDYT?



##########
polaris-core/src/main/java/org/apache/polaris/core/auth/PolarisAuthorizer.java:
##########
@@ -44,7 +44,7 @@ void resolveAuthorizationInputs(
    * Core authorization entry point for the new SPI.
    *
    * <p>Implementations should rely on any required state in {@link 
AuthorizationState} and the
-   * intent captured by {@link AuthorizationRequest} (principal, operation, 
and target securables).
+   * request captured by {@link AuthorizationRequest}.

Review Comment:
   Worth documenting the new batch contract here: intents in one request are 
AND-combined and evaluation short-circuits on the first deny. Important for 
downstream `PolarisAuthorizer` authors.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to