Closes #2348 - adds feature to request the current user via /users?currentUser
Signed-off-by: Kálmán Képes <2853992+nyuuyn@users.noreply.github.com>
This commit is contained in:
parent
44c023746d
commit
208ee77474
|
@ -11,6 +11,9 @@ Whenever a parameter is a complex type, the attributes of the value-object can b
|
||||||
For example, a complex parameter with the name "complex-query-param" and attributes "attribute1" and "attribute2" would be specified in the following way: +
|
For example, a complex parameter with the name "complex-query-param" and attributes "attribute1" and "attribute2" would be specified in the following way: +
|
||||||
complex-query-param={"attribute1":"value1","attribute2":"value2"}
|
complex-query-param={"attribute1":"value1","attribute2":"value2"}
|
||||||
|
|
||||||
|
Whenever a parameter is a value-less type (e.g owner-is-null and current-user) it is expected to be defined without a value,
|
||||||
|
i.e., it should be specified as ?parameter and not ?parameter= or ?parameter=someValue
|
||||||
|
|
||||||
=== Hypermedia Support
|
=== Hypermedia Support
|
||||||
|
|
||||||
NOTE: HATEOAS support is still in development.
|
NOTE: HATEOAS support is still in development.
|
||||||
|
|
|
@ -38,7 +38,7 @@ public class QueryParamsValidator {
|
||||||
checkExactParam(request, "owner-is-null");
|
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();
|
String queryString = request.getQueryString();
|
||||||
boolean containParam = queryString != null && queryString.contains(queryParameter);
|
boolean containParam = queryString != null && queryString.contains(queryParameter);
|
||||||
if (containParam) {
|
if (containParam) {
|
||||||
|
|
|
@ -2,6 +2,8 @@ package pro.taskana.user.rest;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.hateoas.config.EnableHypermediaSupport;
|
import org.springframework.hateoas.config.EnableHypermediaSupport;
|
||||||
import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType;
|
import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType;
|
||||||
|
@ -18,7 +20,9 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import pro.taskana.common.api.exceptions.InvalidArgumentException;
|
import pro.taskana.common.api.exceptions.InvalidArgumentException;
|
||||||
import pro.taskana.common.api.exceptions.NotAuthorizedException;
|
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.RestEndpoints;
|
||||||
|
import pro.taskana.common.rest.util.QueryParamsValidator;
|
||||||
import pro.taskana.user.api.UserService;
|
import pro.taskana.user.api.UserService;
|
||||||
import pro.taskana.user.api.exceptions.UserAlreadyExistException;
|
import pro.taskana.user.api.exceptions.UserAlreadyExistException;
|
||||||
import pro.taskana.user.api.exceptions.UserNotFoundException;
|
import pro.taskana.user.api.exceptions.UserNotFoundException;
|
||||||
|
@ -34,10 +38,15 @@ public class UserController {
|
||||||
private final UserService userService;
|
private final UserService userService;
|
||||||
private final UserRepresentationModelAssembler userAssembler;
|
private final UserRepresentationModelAssembler userAssembler;
|
||||||
|
|
||||||
|
private final CurrentUserContext currentUserContext;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
UserController(UserService userService, UserRepresentationModelAssembler userAssembler) {
|
UserController(UserService userService,
|
||||||
|
UserRepresentationModelAssembler userAssembler,
|
||||||
|
CurrentUserContext currentUserContext) {
|
||||||
this.userService = userService;
|
this.userService = userService;
|
||||||
this.userAssembler = userAssembler;
|
this.userAssembler = userAssembler;
|
||||||
|
this.currentUserContext = currentUserContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,24 +63,39 @@ public class UserController {
|
||||||
public ResponseEntity<UserRepresentationModel> getUser(@PathVariable String userId)
|
public ResponseEntity<UserRepresentationModel> getUser(@PathVariable String userId)
|
||||||
throws UserNotFoundException, InvalidArgumentException {
|
throws UserNotFoundException, InvalidArgumentException {
|
||||||
User user = userService.getUser(userId);
|
User user = userService.getUser(userId);
|
||||||
|
|
||||||
return ResponseEntity.ok(userAssembler.toModel(user));
|
return ResponseEntity.ok(userAssembler.toModel(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint retrieves multiple Users. If a userId can't be found in the database it will be
|
* 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.
|
* 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
|
* @title Get multiple Users
|
||||||
|
* @param request the HttpServletRequest of the request itself
|
||||||
* @param userIds the ids of the requested 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
|
* @return the requested Users
|
||||||
* @throws InvalidArgumentException if the userIds are null or empty
|
* @throws InvalidArgumentException if the userIds are null or empty
|
||||||
|
* @throws UserNotFoundException if the current User was not found
|
||||||
*/
|
*/
|
||||||
@GetMapping(RestEndpoints.URL_USERS)
|
@GetMapping(RestEndpoints.URL_USERS)
|
||||||
@Transactional(readOnly = true, rollbackFor = Exception.class)
|
@Transactional(readOnly = true, rollbackFor = Exception.class)
|
||||||
public ResponseEntity<UserCollectionRepresentationModel> getUsers(
|
public ResponseEntity<UserCollectionRepresentationModel> getUsers(
|
||||||
@RequestParam(name = "user-id") String[] userIds) throws InvalidArgumentException {
|
HttpServletRequest request,
|
||||||
List<User> users = userService.getUsers(new HashSet<>(List.of(userIds)));
|
@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));
|
return ResponseEntity.ok(userAssembler.toTaskanaCollectionModel(users));
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,94 @@ class UserControllerIntTest {
|
||||||
.containsExactlyInAnyOrder("Max", "Elena");
|
.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¤t-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
|
@Test
|
||||||
void should_ReturnExistingUsers_When_ParameterContainsDuplicateAndInvalidIds() throws Exception {
|
void should_ReturnExistingUsers_When_ParameterContainsDuplicateAndInvalidIds() throws Exception {
|
||||||
// also testing different query parameter format
|
// also testing different query parameter format
|
||||||
|
|
Loading…
Reference in New Issue