From c73c6b8ccbb6d7e46f400111cae9c7240051e535 Mon Sep 17 00:00:00 2001 From: Alex Lewin Date: Thu, 7 May 2026 14:59:02 +0100 Subject: [PATCH] Return summary DTO from current_user endpoint & add new endpoint for detailed user object --- .../ac/cam/cl/dtg/segue/api/UsersFacade.java | 55 ++++++++++++++++++- .../api/managers/UserAccountManager.java | 34 ++++++++++-- 2 files changed, 82 insertions(+), 7 deletions(-) diff --git a/src/main/java/uk/ac/cam/cl/dtg/segue/api/UsersFacade.java b/src/main/java/uk/ac/cam/cl/dtg/segue/api/UsersFacade.java index 66e370d045..afc5363eec 100644 --- a/src/main/java/uk/ac/cam/cl/dtg/segue/api/UsersFacade.java +++ b/src/main/java/uk/ac/cam/cl/dtg/segue/api/UsersFacade.java @@ -139,7 +139,7 @@ public UsersFacade(final AbstractConfigLoader properties, final UserAccountManag } /** - * Get the details of the currently logged in user. + * Get a summary of the currently logged-in user. * * @param request * - request information used for caching. @@ -147,15 +147,64 @@ public UsersFacade(final AbstractConfigLoader properties, final UserAccountManag * - the request which may contain session information. * @param response * - the response to set session expiry information headers on. - * @return Returns the current user DTO if we can get it or null response if we can't. It will be a 204 No Content + * @return Returns the current user summary DTO if we can get it or null response if we can't. It will be a 204 No Content */ @GET @Path("users/current_user") @Produces(MediaType.APPLICATION_JSON) - @Operation(summary = "Get information about the current user.") + @Operation(summary = "Get summary information about the current user.") public Response getCurrentUserEndpoint(@Context final Request request, @Context final HttpServletRequest httpServletRequest, @Context final HttpServletResponse response) { + try { + UserSummaryDTO currentUser; + + if (Boolean.parseBoolean(getProperties().getProperty(ALLOW_DIRECT_TEACHER_SIGNUP_AND_FORCE_VERIFICATION))) { + // allow users who are required to verify but haven't yet done so to use this endpoint + currentUser = userManager.getCurrentPartiallyIdentifiedUserSummaryDTO(httpServletRequest, Set.of(AuthenticationCaveat.INCOMPLETE_MANDATORY_EMAIL_VERIFICATION)); + } else { + currentUser = userManager.getCurrentRegisteredUserSummaryDTO(httpServletRequest); + } + + Date sessionExpiry = userManager.getSessionExpiry(httpServletRequest); + int sessionExpiryHashCode = 0; + if (null != sessionExpiry) { + sessionExpiryHashCode = sessionExpiry.hashCode(); + response.setDateHeader("X-Session-Expires", sessionExpiry.getTime()); + } + + // Calculate the ETag based on the user we just retrieved and the session expiry: + EntityTag etag = new EntityTag(currentUser.toString().hashCode() + sessionExpiryHashCode + ""); + Response cachedResponse = generateCachedResponse(request, etag, Constants.NEVER_CACHE_WITHOUT_ETAG_CHECK); + if (cachedResponse != null) { + return cachedResponse; + } + + return Response.ok(currentUser).tag(etag) + .cacheControl(getCacheControl(Constants.NEVER_CACHE_WITHOUT_ETAG_CHECK, false)).build(); + } catch (NoUserLoggedInException e) { + return SegueErrorResponse.getNotLoggedInResponse(); + } + } + + /** + * Get detailed information about the currently logged-in user. + * + * @param request + * - request information used for caching. + * @param httpServletRequest + * - the request which may contain session information. + * @param response + * - the response to set session expiry information headers on. + * @return Returns the current user DTO if we can get it or null response if we can't. It will be a 204 No Content + */ + @GET + @Path("users/current_user/details") + @Produces(MediaType.APPLICATION_JSON) + @Operation(summary = "Get detailed information about the current user.") + public Response getCurrentUserDetailsEndpoint(@Context final Request request, + @Context final HttpServletRequest httpServletRequest, + @Context final HttpServletResponse response) { try { RegisteredUserDTO currentUser; diff --git a/src/main/java/uk/ac/cam/cl/dtg/segue/api/managers/UserAccountManager.java b/src/main/java/uk/ac/cam/cl/dtg/segue/api/managers/UserAccountManager.java index 525896b618..b7c8bec88c 100644 --- a/src/main/java/uk/ac/cam/cl/dtg/segue/api/managers/UserAccountManager.java +++ b/src/main/java/uk/ac/cam/cl/dtg/segue/api/managers/UserAccountManager.java @@ -768,12 +768,12 @@ public final boolean isRegisteredUserLoggedIn(final HttpServletRequest request) } /** - * Get the details of the currently logged in registered user. + * Get the details of the currently logged-in registered user. * *

This method will validate the session and will throw a NoUserLoggedInException if invalid. * * @param request - to retrieve session information from - * @return Returns the current UserDTO if we can get it or null if user is not currently logged in + * @return Returns the current RegisteredUserDTO if we can get it or null if user is not currently logged in * @throws NoUserLoggedInException - When the session has expired or there is no user currently logged in. */ public RegisteredUserDTO getCurrentRegisteredUser(final HttpServletRequest request) @@ -795,6 +795,18 @@ public RegisteredUserDTO getCurrentRegisteredUser(final HttpServletRequest reque return this.convertUserDOToUserDTO(user); } + /** + * Get a summary DTO representing the currently logged-in registered user. + * + * @param request - to retrieve session information from + * @return Returns the current UserSummaryDTO if we can get it or null if user is not currently logged in + * @throws NoUserLoggedInException - When the session has expired or there is no user currently logged in. + */ + public UserSummaryDTO getCurrentRegisteredUserSummaryDTO(final HttpServletRequest request) throws NoUserLoggedInException { + RegisteredUserDTO fullUser = getCurrentRegisteredUser(request); + return dtoMapper.mapToUserSummaryDTO(fullUser); + } + /** * Extract the session expiry time from a request. * @@ -1569,10 +1581,10 @@ public List convertToDetailedUserSummaryObjectLi * specific purposes, e.g. responding to MFA challenge after a correct email/password login. * * @param request to pull back the user - * @return UserSummaryDTO of the partially logged-in user or will throw an exception if not found or the session has unacceptable caveats. + * @return RegisteredUserDTO of the partially logged-in user or will throw an exception if not found or the session has unacceptable caveats. * @throws NoUserLoggedInException if they haven't started the flow. */ - public RegisteredUserDTO getCurrentPartiallyIdentifiedUser(HttpServletRequest request, Set acceptableCaveats) throws NoUserLoggedInException { + public RegisteredUserDTO getCurrentPartiallyIdentifiedUser(final HttpServletRequest request, final Set acceptableCaveats) throws NoUserLoggedInException { RegisteredUser registeredUser = this.retrieveCaveatLogin(request, acceptableCaveats); if (null == registeredUser) { throw new NoUserLoggedInException(); @@ -1580,6 +1592,20 @@ public RegisteredUserDTO getCurrentPartiallyIdentifiedUser(HttpServletRequest re return this.convertUserDOToUserDTO(registeredUser); } + /** + * Get a summary DTO representing the user from the session cookie, overlooking the specified caveats if present (but not others). + * + * @see #getCurrentPartiallyIdentifiedUser(HttpServletRequest, Set) for restrictions on when this should be used. + * + * @param request to pull back the user + * @return UserSummaryDTO of the partially logged-in user or will throw an exception if not found or the session has unacceptable caveats. + * @throws NoUserLoggedInException if they haven't started the flow. + */ + public UserSummaryDTO getCurrentPartiallyIdentifiedUserSummaryDTO(final HttpServletRequest request, final Set acceptableCaveats) throws NoUserLoggedInException { + RegisteredUserDTO fullUser = getCurrentPartiallyIdentifiedUser(request, acceptableCaveats); + return dtoMapper.mapToUserSummaryDTO(fullUser); + } + /** * Sends verification email for the user's current email address. The destination will match the userDTO's email. *