This is an automated email from the ASF dual-hosted git repository. github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-7057-b98faf4d1c8ff4a60d8282fe906167568f178992 in repository https://gitbox.apache.org/repos/asf/texera.git
commit ffbda031344176dbba2820406ac418b36d273c67 Author: Neil Ketteringham <[email protected]> AuthorDate: Thu Jul 30 12:29:25 2026 -0700 refactor(auth): construct User via .tap instead of positional constructor (#7057) ### What changes were proposed in this PR? Classes relying on the POJO User generated by jOOq uses its positional constructor which is fragile and requires us to refactor every constructor every time we edit the User table even if the new fields aren't used. Most instances of User() called it with mostly null fields which is hard to read and isn't very clear. This PR changes that by using the .tap{} feature of Scala which allows you to construct and modify objects in place before assigned as a parameter or variable. This allows code like this: ```scala val GUEST: User = new User(null, "guest", null, null, null, null, UserRoleEnum.REGULAR, null, null, null, null) ``` To be rewritten like this ```scala val GUEST: User = { new User().tap { user => user.setName("guest") user.setRole(UserRoleEnum.REGULAR) } } ``` ### Any related issues, documentation, discussions? Closes #7044 ### How was this PR tested? PR was tested against current test suite. ### Was this PR authored or co-authored using generative AI tooling? No. --- .../activity/UserActivityEventListenerSpec.scala | 10 ++++-- .../texera/web/ServletAwareConfigurator.scala | 37 +++++++--------------- .../apache/texera/web/auth/GuestAuthFilter.scala | 7 ++-- .../scala/org/apache/texera/auth/JwtParser.scala | 24 +++++++------- 4 files changed, 35 insertions(+), 43 deletions(-) diff --git a/access-control-service/src/test/scala/org/apache/texera/service/activity/UserActivityEventListenerSpec.scala b/access-control-service/src/test/scala/org/apache/texera/service/activity/UserActivityEventListenerSpec.scala index 3d99f4e7fb..e0cfee03c5 100644 --- a/access-control-service/src/test/scala/org/apache/texera/service/activity/UserActivityEventListenerSpec.scala +++ b/access-control-service/src/test/scala/org/apache/texera/service/activity/UserActivityEventListenerSpec.scala @@ -31,12 +31,18 @@ import org.scalatest.matchers.should.Matchers import java.security.Principal import java.util.concurrent.ConcurrentLinkedQueue +import scala.util.chaining.scalaUtilChainingOps class UserActivityEventListenerSpec extends AnyFlatSpec with Matchers { private def sessionUser(uid: Integer): SessionUser = { - val u = new User(uid, "u", null, null, null, null, UserRoleEnum.REGULAR, null, null, null, null) - new SessionUser(u) + new SessionUser( + new User().tap { user => + user.setUid(uid) + user.setName("u") + user.setRole(UserRoleEnum.REGULAR) + } + ) } private def buildEvent(eventType: RequestEvent.Type, sc: SecurityContext): RequestEvent = { diff --git a/amber/src/main/scala/org/apache/texera/web/ServletAwareConfigurator.scala b/amber/src/main/scala/org/apache/texera/web/ServletAwareConfigurator.scala index cb3628df5b..2e2fc6e082 100644 --- a/amber/src/main/scala/org/apache/texera/web/ServletAwareConfigurator.scala +++ b/amber/src/main/scala/org/apache/texera/web/ServletAwareConfigurator.scala @@ -31,6 +31,7 @@ import java.nio.charset.Charset import javax.websocket.HandshakeResponse import javax.websocket.server.{HandshakeRequest, ServerEndpointConfig} import scala.jdk.CollectionConverters.{ListHasAsScala, _} +import scala.util.chaining.scalaUtilChainingOps /** * This configurator extracts user identity from the HTTP handshake request @@ -66,19 +67,11 @@ class ServletAwareConfigurator extends ServerEndpointConfig.Configurator with La config.getUserProperties.put( classOf[User].getName, - new User( - userId, - userName, - userEmail, - null, - null, - null, - null, - null, - null, - null, - null - ) + new User().tap { user => + user.setUid(userId) + user.setName(userName) + user.setEmail(userEmail) + } ) logger.debug(s"User created from headers: ID=$userId, Name=$userName") } else { @@ -97,19 +90,11 @@ class ServletAwareConfigurator extends ServerEndpointConfig.Configurator with La val claims = jwtConsumer.process(token).getJwtClaims config.getUserProperties.put( classOf[User].getName, - new User( - claims.getClaimValue("userId").asInstanceOf[Long].toInt, - claims.getSubject, - String.valueOf(claims.getClaimValue("email").asInstanceOf[String]), - null, - null, - null, - null, - null, - null, - null, - null - ) + new User().tap { user => + user.setUid(claims.getClaimValue("userId").asInstanceOf[Long].toInt) + user.setName(claims.getSubject) + user.setEmail(claims.getClaimValue("email").asInstanceOf[String]) + } ) }) } diff --git a/amber/src/main/scala/org/apache/texera/web/auth/GuestAuthFilter.scala b/amber/src/main/scala/org/apache/texera/web/auth/GuestAuthFilter.scala index b7dda09489..8682335e82 100644 --- a/amber/src/main/scala/org/apache/texera/web/auth/GuestAuthFilter.scala +++ b/amber/src/main/scala/org/apache/texera/web/auth/GuestAuthFilter.scala @@ -31,6 +31,7 @@ import javax.annotation.{Nullable, Priority} import javax.ws.rs.Priorities import javax.ws.rs.container.{ContainerRequestContext, PreMatching} import javax.ws.rs.core.SecurityContext +import scala.util.chaining.scalaUtilChainingOps @PreMatching @Priority(Priorities.AUTHENTICATION) object GuestAuthFilter { @@ -38,8 +39,10 @@ import javax.ws.rs.core.SecurityContext override protected def newInstance = new GuestAuthFilter } - val GUEST: User = - new User(null, "guest", null, null, null, null, UserRoleEnum.REGULAR, null, null, null, null) + val GUEST: User = new User().tap { user => + user.setName("guest") + user.setRole(UserRoleEnum.REGULAR) + } } @PreMatching diff --git a/common/auth/src/main/scala/org/apache/texera/auth/JwtParser.scala b/common/auth/src/main/scala/org/apache/texera/auth/JwtParser.scala index bb139e7093..cf324b0959 100644 --- a/common/auth/src/main/scala/org/apache/texera/auth/JwtParser.scala +++ b/common/auth/src/main/scala/org/apache/texera/auth/JwtParser.scala @@ -26,6 +26,7 @@ import org.jose4j.jwt.JwtClaims import org.jose4j.lang.UnresolvableKeyException import java.util.Optional +import scala.util.chaining.scalaUtilChainingOps /** Single source of truth for converting a verified JWT into a [[SessionUser]]. * @@ -63,19 +64,16 @@ object JwtParser extends LazyLogging { val role = UserRoleEnum.valueOf(claims.getClaimValue("role").asInstanceOf[String]) val googleId = claims.getClaimValue("googleId", classOf[String]) val googleAvatar = claims.getClaimValue("googleAvatar", classOf[String]) - val user = new User( - userId, - userName, - email, - null, - googleId, - googleAvatar, - role, - null, - null, - null, - null + + new SessionUser( + new User().tap { user => + user.setUid(userId) + user.setName(userName) + user.setEmail(email) + user.setRole(role) + user.setGoogleId(googleId) + user.setGoogleAvatar(googleAvatar) + } ) - new SessionUser(user) } }
