Skip to content

Commit

Permalink
Closes #2348 - adds feature to request the current user via /users?cu…
Browse files Browse the repository at this point in the history
…rrentUser

Signed-off-by: Kálmán Képes <[email protected]>
  • Loading branch information
nyuuyn committed Aug 10, 2023
1 parent 7e2f933 commit 6a4be92
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public static void validateParams(HttpServletRequest request, Class<?>... filter
checkExactParam(request, "owner-is-null");
}

private static void checkExactParam(HttpServletRequest request, String queryParameter) {
public static void checkExactParam(HttpServletRequest request, String queryParameter) {
String queryString = request.getQueryString();
boolean containParam = queryString != null && queryString.contains(queryParameter);
if (containParam) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.config.EnableHypermediaSupport;
import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType;
Expand All @@ -18,7 +19,9 @@
import org.springframework.web.bind.annotation.RestController;
import pro.taskana.common.api.exceptions.InvalidArgumentException;
import pro.taskana.common.api.exceptions.NotAuthorizedException;
import pro.taskana.common.api.security.CurrentUserContext;
import pro.taskana.common.rest.RestEndpoints;
import pro.taskana.common.rest.util.QueryParamsValidator;
import pro.taskana.user.api.UserService;
import pro.taskana.user.api.exceptions.UserAlreadyExistException;
import pro.taskana.user.api.exceptions.UserNotFoundException;
Expand All @@ -27,17 +30,24 @@
import pro.taskana.user.rest.models.UserCollectionRepresentationModel;
import pro.taskana.user.rest.models.UserRepresentationModel;

import javax.servlet.http.HttpServletRequest;

/** Controller for all {@linkplain User} related endpoints. */
@RestController
@EnableHypermediaSupport(type = HypermediaType.HAL)
public class UserController {
private final UserService userService;
private final UserRepresentationModelAssembler userAssembler;

private final CurrentUserContext currentUserContext;

@Autowired
UserController(UserService userService, UserRepresentationModelAssembler userAssembler) {
UserController(UserService userService,
UserRepresentationModelAssembler userAssembler,
CurrentUserContext currentUserContext) {
this.userService = userService;
this.userAssembler = userAssembler;
this.currentUserContext = currentUserContext;
}

/**
Expand All @@ -54,24 +64,38 @@ public class UserController {
public ResponseEntity<UserRepresentationModel> getUser(@PathVariable String userId)
throws UserNotFoundException, InvalidArgumentException {
User user = userService.getUser(userId);

return ResponseEntity.ok(userAssembler.toModel(user));
}

/**
* This endpoint retrieves multiple Users. If a userId can't be found in the database it will be
* ignored. If none of the given userIds is valid, the returned list will be empty.
* If currentUser is set, the current User from the context will be retrieved as well
*
* @title Get multiple Users
* @param userIds the ids of the requested Users
* @param currentUser Indicates whether to fetch the current user or not as well
* @return the requested Users
* @throws InvalidArgumentException if the userIds are null or empty
* @throws UserNotFoundException if the current User was not found
*/
@GetMapping(RestEndpoints.URL_USERS)
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<UserCollectionRepresentationModel> getUsers(
@RequestParam(name = "user-id") String[] userIds) throws InvalidArgumentException {
List<User> users = userService.getUsers(new HashSet<>(List.of(userIds)));
HttpServletRequest request,
@RequestParam(name = "user-id", required = false) String[] userIds,
@RequestParam(name = "current-user", required = false) String currentUser)
throws InvalidArgumentException, UserNotFoundException {
Set<User> users = new HashSet<>();

if (userIds != null) {
users.addAll(userService.getUsers(new HashSet<>(List.of(userIds))));
}

if (currentUser != null) {
QueryParamsValidator.checkExactParam(request, "current-user");
users.add(userService.getUser(this.currentUserContext.getUserid()));
}

return ResponseEntity.ok(userAssembler.toTaskanaCollectionModel(users));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,94 @@ void should_ReturnExistingUsers() throws Exception {
.containsExactlyInAnyOrder("Max", "Elena");
}

@Test
void should_ReturnCurrentUser() {
String url = restHelper.toUrl(RestEndpoints.URL_USERS) + "?current-user";
HttpEntity<?> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));

ResponseEntity<UserCollectionRepresentationModel> response =
TEMPLATE.exchange(
url,
HttpMethod.GET,
auth,
ParameterizedTypeReference.forType(UserCollectionRepresentationModel.class));
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getContent()).hasSize(1);
assertThat(response.getBody().getContent()).extracting("userId").containsExactly("teamlead-1");
}

@Test
void should_ReturnExceptionCurrentUserWithBadValue() {
String url = restHelper.toUrl(RestEndpoints.URL_USERS) + "?current-user=asd";
HttpEntity<?> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));

ThrowingCallable httpCall =
() -> TEMPLATE.exchange(
url,
HttpMethod.GET,
auth,
ParameterizedTypeReference.forType(UserCollectionRepresentationModel.class));
assertThatThrownBy(httpCall)
.isInstanceOf(HttpStatusCodeException.class)
.extracting(HttpStatusCodeException.class::cast)
.extracting(HttpStatusCodeException::getStatusCode)
.isEqualTo(HttpStatus.BAD_REQUEST);
}

@Test
void should_ReturnExceptionCurrentUserWithEmptyValue() {
String url = restHelper.toUrl(RestEndpoints.URL_USERS) + "?current-user=";
HttpEntity<?> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));

ThrowingCallable httpCall =
() -> TEMPLATE.exchange(
url,
HttpMethod.GET,
auth,
ParameterizedTypeReference.forType(UserCollectionRepresentationModel.class));
assertThatThrownBy(httpCall)
.isInstanceOf(HttpStatusCodeException.class)
.extracting(HttpStatusCodeException.class::cast)
.extracting(HttpStatusCodeException::getStatusCode)
.isEqualTo(HttpStatus.BAD_REQUEST);
}

@Test
void should_ReturnOnlyCurrentUserWhileUsingUserIds() {
String url = restHelper.toUrl(RestEndpoints.URL_USERS) + "?current-user&user-id=teamlead-1";
HttpEntity<?> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));

ResponseEntity<UserCollectionRepresentationModel> response =
TEMPLATE.exchange(
url,
HttpMethod.GET,
auth,
ParameterizedTypeReference.forType(UserCollectionRepresentationModel.class));
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getContent()).hasSize(1);
assertThat(response.getBody().getContent()).extracting("userId").containsExactly("teamlead-1");
}

@Test
void should_ReturnExistingUsersAndCurrentUser() throws Exception {
String url = restHelper.toUrl(RestEndpoints.URL_USERS)
+ "?user-id=user-1-1&user-id=USER-1-2&current-user";
HttpEntity<?> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));

ResponseEntity<UserCollectionRepresentationModel> responseEntity =
TEMPLATE.exchange(
url,
HttpMethod.GET,
auth,
ParameterizedTypeReference.forType(UserCollectionRepresentationModel.class));
UserCollectionRepresentationModel response = responseEntity.getBody();
assertThat(response).isNotNull();
assertThat(response.getContent()).hasSize(3);
assertThat(response.getContent())
.extracting("userId")
.containsExactlyInAnyOrder("user-1-1", "user-1-2", "teamlead-1");
}

@Test
void should_ReturnExistingUsers_When_ParameterContainsDuplicateAndInvalidIds() throws Exception {
// also testing different query parameter format
Expand Down

0 comments on commit 6a4be92

Please sign in to comment.