TSK-1308: User must be in role ADMIN, BUSINESS_ADMIN to use AccessIdSrv.

This commit is contained in:
holgerhagen 2020-06-26 14:38:42 +02:00 committed by Mustapha Zorgati
parent 553c1d9f83
commit 382b8366bf
5 changed files with 71 additions and 25 deletions

View File

@ -11,7 +11,10 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam; 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.TaskanaEngine;
import pro.taskana.common.api.TaskanaRole;
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.rest.ldap.LdapClient; import pro.taskana.common.rest.ldap.LdapClient;
import pro.taskana.common.rest.models.AccessIdRepresentationModel; import pro.taskana.common.rest.models.AccessIdRepresentationModel;
@ -26,19 +29,24 @@ public class AccessIdController {
private static final Logger LOGGER = LoggerFactory.getLogger(AccessIdController.class); private static final Logger LOGGER = LoggerFactory.getLogger(AccessIdController.class);
LdapClient ldapClient; private final LdapClient ldapClient;
private final TaskanaEngine taskanaEngine;
@Autowired @Autowired
public AccessIdController(LdapClient ldapClient) { public AccessIdController(LdapClient ldapClient, TaskanaEngine taskanaEngine) {
this.ldapClient = ldapClient; this.ldapClient = ldapClient;
this.taskanaEngine = taskanaEngine;
} }
@GetMapping(path = Mapping.URL_ACCESSID) @GetMapping(path = Mapping.URL_ACCESSID)
public ResponseEntity<List<AccessIdRepresentationModel>> validateAccessIds( public ResponseEntity<List<AccessIdRepresentationModel>> validateAccessIds(
@RequestParam("search-for") String searchFor) throws InvalidArgumentException { @RequestParam("search-for") String searchFor)
throws InvalidArgumentException, NotAuthorizedException {
LOGGER.debug("Entry to validateAccessIds(search-for= {})", searchFor); LOGGER.debug("Entry to validateAccessIds(search-for= {})", searchFor);
taskanaEngine.checkRoleMembership(TaskanaRole.ADMIN, TaskanaRole.BUSINESS_ADMIN);
if (searchFor.length() < ldapClient.getMinSearchForLength()) { if (searchFor.length() < ldapClient.getMinSearchForLength()) {
throw new InvalidArgumentException( throw new InvalidArgumentException(
"searchFor string '" "searchFor string '"
@ -58,19 +66,24 @@ public class AccessIdController {
@GetMapping(path = Mapping.URL_ACCESSID_GROUPS) @GetMapping(path = Mapping.URL_ACCESSID_GROUPS)
public ResponseEntity<List<AccessIdRepresentationModel>> getGroupsByAccessId( public ResponseEntity<List<AccessIdRepresentationModel>> getGroupsByAccessId(
@RequestParam("access-id") String accessId) throws InvalidArgumentException { @RequestParam("access-id") String accessId)
throws InvalidArgumentException, NotAuthorizedException {
LOGGER.debug("Entry to getGroupsByAccessId(access-id= {})", accessId); LOGGER.debug("Entry to getGroupsByAccessId(access-id= {})", accessId);
taskanaEngine.checkRoleMembership(TaskanaRole.ADMIN, TaskanaRole.BUSINESS_ADMIN);
if (!validateAccessId(accessId)) { if (!validateAccessId(accessId)) {
throw new InvalidArgumentException("The accessId is invalid"); throw new InvalidArgumentException("The accessId is invalid");
} }
List<AccessIdRepresentationModel> accessIds;
ResponseEntity<List<AccessIdRepresentationModel>> response; List<AccessIdRepresentationModel> accessIds =
accessIds = ldapClient.searchGroupsAccessIdIsMemberOf(accessId); ldapClient.searchGroupsAccessIdIsMemberOf(accessId);
response = ResponseEntity.ok(accessIds); ResponseEntity<List<AccessIdRepresentationModel>> response = ResponseEntity.ok(accessIds);
if (LOGGER.isDebugEnabled()) { if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Exit from getGroupsByAccessId(), returning {}", response); LOGGER.debug("Exit from getGroupsByAccessId(), returning {}", response);
} }
return response; return response;
} }

View File

@ -183,15 +183,15 @@ public class LdapClient {
return accessId; return accessId;
} }
public List<AccessIdRepresentationModel> searchGroupsAccessIdIsMemberOf(final String name) public List<AccessIdRepresentationModel> searchGroupsAccessIdIsMemberOf(final String accessId)
throws InvalidArgumentException { throws InvalidArgumentException {
LOGGER.debug("entry to searchGroupsAccessIdIsMemberOf(name = {}).", name); LOGGER.debug("entry to searchGroupsAccessIdIsMemberOf(name = {}).", accessId);
isInitOrFail(); isInitOrFail();
testMinSearchForLength(name); testMinSearchForLength(accessId);
final AndFilter andFilter = new AndFilter(); final AndFilter andFilter = new AndFilter();
andFilter.and(new EqualsFilter(getGroupSearchFilterName(), getGroupSearchFilterValue())); andFilter.and(new EqualsFilter(getGroupSearchFilterName(), getGroupSearchFilterValue()));
andFilter.and(new LikeFilter(getGroupsOfUser(), "*" + name + "*")); andFilter.and(new LikeFilter(getGroupsOfUser(), "*" + accessId + "*"));
String[] userAttributesToReturn = {getUserIdAttribute(), getGroupNameAttribute()}; String[] userAttributesToReturn = {getUserIdAttribute(), getGroupNameAttribute()};
@ -202,6 +202,7 @@ public class LdapClient {
SearchControls.SUBTREE_SCOPE, SearchControls.SUBTREE_SCOPE,
userAttributesToReturn, userAttributesToReturn,
new GroupContextMapper()); new GroupContextMapper());
LOGGER.debug( LOGGER.debug(
"exit from searchGroupsAccessIdIsMemberOf. Retrieved the following accessIds: {}.", "exit from searchGroupsAccessIdIsMemberOf. Retrieved the following accessIds: {}.",
accessIds); accessIds);

View File

@ -10,6 +10,7 @@ import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@ -116,16 +117,16 @@ class AccessIdControllerIntTest {
restHelper.defaultRequest(), restHelper.defaultRequest(),
ParameterizedTypeReference.forType(AccessIdListResource.class)); ParameterizedTypeReference.forType(AccessIdListResource.class));
List<AccessIdRepresentationModel> body = response.getBody(); assertThat(response.getBody())
assertThat(body).isNotNull(); .isNotNull()
assertThat(body)
.extracting(AccessIdRepresentationModel::getAccessId) .extracting(AccessIdRepresentationModel::getAccessId)
.usingElementComparator(String.CASE_INSENSITIVE_ORDER) .usingElementComparator(String.CASE_INSENSITIVE_ORDER)
.containsExactlyInAnyOrder( .containsExactlyInAnyOrder(
"cn=ksc-teamleads,cn=groups,OU=Test,O=TASKANA", "cn=ksc-teamleads,cn=groups,OU=Test,O=TASKANA",
"cn=business-admins,cn=groups,OU=Test,O=TASKANA", "cn=business-admins,cn=groups,OU=Test,O=TASKANA",
"cn=monitor-users,cn=groups,OU=Test,O=TASKANA", "cn=monitor-users,cn=groups,OU=Test,O=TASKANA",
"cn=Organisationseinheit KSC 2,cn=Organisationseinheit KSC,cn=organisation,OU=Test,O=TASKANA"); "cn=Organisationseinheit KSC 2,"
+ "cn=Organisationseinheit KSC,cn=organisation,OU=Test,O=TASKANA");
} }
@Test @Test
@ -139,14 +140,45 @@ class AccessIdControllerIntTest {
restHelper.defaultRequest(), restHelper.defaultRequest(),
ParameterizedTypeReference.forType(AccessIdListResource.class)); ParameterizedTypeReference.forType(AccessIdListResource.class));
List<AccessIdRepresentationModel> body = response.getBody(); assertThat(response.getBody())
assertThat(body).isNotNull(); .isNotNull()
assertThat(body)
.extracting(AccessIdRepresentationModel::getAccessId) .extracting(AccessIdRepresentationModel::getAccessId)
.usingElementComparator(String.CASE_INSENSITIVE_ORDER) .usingElementComparator(String.CASE_INSENSITIVE_ORDER)
.containsExactlyInAnyOrder("cn=Organisationseinheit KSC,cn=organisation,OU=Test,O=TASKANA"); .containsExactlyInAnyOrder("cn=Organisationseinheit KSC,cn=organisation,OU=Test,O=TASKANA");
} }
@Test
void should_throwNotAuthorizedException_ifCallerOfGroupRetrievalIsNotAdminOrBusinessAdmin() {
ThrowingCallable call =
() ->
template.exchange(
restHelper.toUrl(Mapping.URL_ACCESSID_GROUPS) + "?access-id=teamlead-2",
HttpMethod.GET,
new HttpEntity<>(restHelper.getHeadersUser_1_1()),
ParameterizedTypeReference.forType(AccessIdListResource.class));
assertThatThrownBy(call)
.isInstanceOf(HttpClientErrorException.class)
.extracting(ex -> ((HttpClientErrorException) ex).getStatusCode())
.isEqualTo(HttpStatus.FORBIDDEN);
}
@Test
void should_throwNotAuthorizedException_ifCallerOfValidationIsNotAdminOrBusinessAdmin() {
ThrowingCallable call =
() ->
template.exchange(
restHelper.toUrl(Mapping.URL_ACCESSID) + "?search-for=al",
HttpMethod.GET,
new HttpEntity<>(restHelper.getHeadersUser_1_1()),
ParameterizedTypeReference.forType(AccessIdListResource.class));
assertThatThrownBy(call)
.isInstanceOf(HttpClientErrorException.class)
.extracting(ex -> ((HttpClientErrorException) ex).getStatusCode())
.isEqualTo(HttpStatus.FORBIDDEN);
}
static class AccessIdListResource extends ArrayList<AccessIdRepresentationModel> { static class AccessIdListResource extends ArrayList<AccessIdRepresentationModel> {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
} }

View File

@ -83,7 +83,7 @@ class TaskControllerIntTest {
TASK_SUMMARY_PAGE_MODEL_TYPE); TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull(); assertThat(response.getBody()).isNotNull();
assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(25); assertThat(response.getBody().getContent()).hasSize(48);
} }
@Test @Test
@ -465,7 +465,7 @@ class TaskControllerIntTest {
request, request,
TASK_SUMMARY_PAGE_MODEL_TYPE); TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull(); assertThat(response.getBody()).isNotNull();
assertThat((response.getBody()).getContent()).hasSize(25); assertThat((response.getBody()).getContent()).hasSize(48);
response = response =
TEMPLATE.exchange( TEMPLATE.exchange(
@ -476,8 +476,8 @@ class TaskControllerIntTest {
assertThat(response.getBody()).isNotNull(); assertThat(response.getBody()).isNotNull();
assertThat((response.getBody()).getContent()).hasSize(5); assertThat((response.getBody()).getContent()).hasSize(5);
assertThat(response.getBody().getRequiredLink(IanaLinkRelations.LAST).getHref()) assertThat(response.getBody().getRequiredLink(IanaLinkRelations.LAST).getHref())
.contains("page=5"); .contains("page=10");
assertThat("TKI:000000000000000000000000000000000023") assertThat("TKI:000000000000000000000000000000000005")
.isEqualTo(response.getBody().getContent().iterator().next().getTaskId()); .isEqualTo(response.getBody().getContent().iterator().next().getTaskId());
assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull();

View File

@ -82,7 +82,7 @@ class WorkbasketControllerIntTest {
WORKBASKET_SUMMARY_PAGE_MODEL_TYPE); WORKBASKET_SUMMARY_PAGE_MODEL_TYPE);
assertThat(response.getBody()).isNotNull(); assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getRequiredLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getRequiredLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getContent()).hasSize(3); assertThat(response.getBody().getContent()).hasSize(6);
} }
@Test @Test