/*
* Copyright 2013-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.cloudfoundry.uaa;
import org.cloudfoundry.AbstractIntegrationTest;
import org.cloudfoundry.uaa.groups.AddMemberRequest;
import org.cloudfoundry.uaa.groups.CheckMembershipRequest;
import org.cloudfoundry.uaa.groups.CreateGroupRequest;
import org.cloudfoundry.uaa.groups.CreateGroupResponse;
import org.cloudfoundry.uaa.groups.DeleteGroupRequest;
import org.cloudfoundry.uaa.groups.DeleteGroupResponse;
import org.cloudfoundry.uaa.groups.ExternalGroupResource;
import org.cloudfoundry.uaa.groups.GetGroupRequest;
import org.cloudfoundry.uaa.groups.GetGroupResponse;
import org.cloudfoundry.uaa.groups.Group;
import org.cloudfoundry.uaa.groups.ListExternalGroupMappingsRequest;
import org.cloudfoundry.uaa.groups.ListGroupsRequest;
import org.cloudfoundry.uaa.groups.ListMembersRequest;
import org.cloudfoundry.uaa.groups.ListMembersResponse;
import org.cloudfoundry.uaa.groups.MapExternalGroupRequest;
import org.cloudfoundry.uaa.groups.MapExternalGroupResponse;
import org.cloudfoundry.uaa.groups.Member;
import org.cloudfoundry.uaa.groups.MemberSummary;
import org.cloudfoundry.uaa.groups.MemberType;
import org.cloudfoundry.uaa.groups.RemoveMemberRequest;
import org.cloudfoundry.uaa.groups.RemoveMemberResponse;
import org.cloudfoundry.uaa.groups.UnmapExternalGroupByGroupDisplayNameRequest;
import org.cloudfoundry.uaa.groups.UnmapExternalGroupByGroupIdRequest;
import org.cloudfoundry.uaa.groups.UpdateGroupRequest;
import org.cloudfoundry.uaa.groups.UserEntity;
import org.cloudfoundry.uaa.users.CreateUserRequest;
import org.cloudfoundry.uaa.users.CreateUserResponse;
import org.cloudfoundry.uaa.users.Email;
import org.cloudfoundry.uaa.users.Name;
import org.cloudfoundry.util.PaginationUtils;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.TimeoutException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.cloudfoundry.util.OperationUtils.thenKeep;
import static org.cloudfoundry.util.tuple.TupleUtils.consumer;
import static org.cloudfoundry.util.tuple.TupleUtils.function;
public final class GroupsTest extends AbstractIntegrationTest {
@Autowired
private UaaClient uaaClient;
@Test
public void addMemberGroup() throws TimeoutException, InterruptedException {
String baseDisplayName = this.nameFactory.getGroupName();
String memberDisplayName = this.nameFactory.getGroupName();
Mono
.when(
createGroupId(this.uaaClient, baseDisplayName),
createGroupId(this.uaaClient, memberDisplayName)
)
.then(function((baseGroupId, memberGroupId) -> Mono.when(
this.uaaClient.groups()
.addMember(AddMemberRequest.builder()
.groupId(baseGroupId)
.origin(memberDisplayName + "-origin")
.type(MemberType.GROUP)
.memberId(memberGroupId)
.build()),
Mono.just(memberGroupId)
)))
.as(StepVerifier::create)
.consumeNextWith(consumer((response, memberGroupId) -> {
assertThat(response.getMemberId()).isEqualTo(memberGroupId);
assertThat(response.getOrigin()).isEqualTo(Optional.of(String.format("%s-origin", memberDisplayName)));
assertThat(response.getType()).isEqualTo(Optional.of(MemberType.GROUP));
}))
.expectComplete()
.verify(Duration.ofMinutes(5));
}
@Test
public void addMemberUser() throws TimeoutException, InterruptedException {
String displayName = this.nameFactory.getGroupName();
String userName = this.nameFactory.getUserName();
Mono.
when(
createGroupId(this.uaaClient, displayName),
createUserId(this.uaaClient, userName)
)
.then(function((groupId, userId) -> Mono.when(
this.uaaClient.groups()
.addMember(AddMemberRequest.builder()
.groupId(groupId)
.origin(userName + "-origin")
.type(MemberType.USER)
.memberId(userId)
.build()),
Mono.just(userId)
)))
.as(StepVerifier::create)
.consumeNextWith(consumer((response, userId) -> {
assertThat(response.getMemberId()).isEqualTo(userId);
assertThat(response.getOrigin()).isEqualTo(Optional.of(String.format("%s-origin", userName)));
assertThat(response.getType()).isEqualTo(Optional.of(MemberType.USER));
}))
.expectComplete()
.verify(Duration.ofMinutes(5));
}
@Test
public void checkMembership() throws TimeoutException, InterruptedException {
String displayName = this.nameFactory.getGroupName();
String userName = this.nameFactory.getUserName();
createUserId(this.uaaClient, userName)
.then(userId -> Mono.when(
createGroupIdWithMember(this.uaaClient, displayName, userId),
Mono.just(userId)
))
.then(function((groupId, userId) -> Mono.when(
this.uaaClient.groups()
.checkMembership(CheckMembershipRequest.builder()
.groupId(groupId)
.memberId(userId)
.build()),
Mono.just(userId)
)))
.as(StepVerifier::create)
.consumeNextWith(consumer((response, userId) -> {
assertThat(response.getMemberId()).isEqualTo(userId);
assertThat(response.getOrigin()).isEqualTo(Optional.of("test-origin"));
assertThat(response.getType()).isEqualTo(Optional.of(MemberType.USER));
}))
.expectComplete()
.verify(Duration.ofMinutes(5));
}
@Test
public void create() throws TimeoutException, InterruptedException {
String displayName = this.nameFactory.getGroupName();
String userName = this.nameFactory.getUserName();
createUserId(this.uaaClient, userName)
.then(userId -> this.uaaClient.groups()
.create(CreateGroupRequest.builder()
.displayName(displayName)
.member(MemberSummary.builder()
.memberId(userId)
.build())
.build()))
.then(requestList(this.uaaClient)
.filter(resource -> displayName.equals(resource.getDisplayName()))
.single())
.as(StepVerifier::create)
.expectNextCount(1)
.expectComplete()
.verify(Duration.ofMinutes(5));
}
@Test
public void delete() throws TimeoutException, InterruptedException {
String displayName = this.nameFactory.getGroupName();
createGroupId(this.uaaClient, displayName)
.then(groupId -> this.uaaClient.groups()
.delete(DeleteGroupRequest.builder()
.groupId(groupId)
.build()))
.map(DeleteGroupResponse::getDisplayName)
.as(StepVerifier::create)
.expectNext(displayName)
.expectComplete()
.verify(Duration.ofMinutes(5));
}
@Test
public void get() throws TimeoutException, InterruptedException {
String displayName = this.nameFactory.getGroupName();
createGroupId(this.uaaClient, displayName)
.then(groupId -> this.uaaClient.groups()
.get(GetGroupRequest.builder()
.groupId(groupId)
.build())
.map(GetGroupResponse::getDisplayName))
.as(StepVerifier::create)
.expectNext(displayName)
.expectComplete()
.verify(Duration.ofMinutes(5));
}
@Test
public void list() throws TimeoutException, InterruptedException {
String displayName = this.nameFactory.getGroupName();
createGroupId(this.uaaClient, displayName)
.then(groupId -> PaginationUtils
.requestUaaResources(startIndex -> this.uaaClient.groups()
.list(ListGroupsRequest.builder()
.filter(String.format("id eq \"%s\"", groupId))
.startIndex(startIndex)
.build()))
.single())
.map(Group::getDisplayName)
.as(StepVerifier::create)
.expectNext(displayName)
.expectComplete()
.verify(Duration.ofMinutes(5));
}
@Test
public void listExternalGroupMappings() throws TimeoutException, InterruptedException {
String displayName = this.nameFactory.getGroupName();
createGroupId(this.uaaClient, displayName)
.then(groupId -> requestMapExternalGroupResponse(this.uaaClient, displayName, groupId))
.thenMany(PaginationUtils
.requestUaaResources(startIndex -> this.uaaClient.groups()
.listExternalGroupMappings(ListExternalGroupMappingsRequest.builder()
.startIndex(startIndex)
.build()))
.filter(group -> displayName.equals(group.getDisplayName())))
.map(ExternalGroupResource::getExternalGroup)
.as(StepVerifier::create)
.expectNext(displayName + "-external-group")
.expectComplete()
.verify(Duration.ofMinutes(5));
}
@Test
public void listMembers() throws TimeoutException, InterruptedException {
String displayName = this.nameFactory.getGroupName();
String userName = this.nameFactory.getUserName();
createUserId(this.uaaClient, userName)
.then(userId -> Mono.when(
createGroupIdWithMember(this.uaaClient, displayName, userId),
Mono.just(userId)
))
.then(function((groupId, userId) -> Mono.when(
this.uaaClient.groups()
.listMembers(ListMembersRequest.builder()
.groupId(groupId)
.returnEntities(false)
.build())
.flatMapIterable(ListMembersResponse::getMembers)
.map(Member::getMemberId)
.single(),
Mono.just(userId)
)))
.as(StepVerifier::create)
.consumeNextWith(tupleEquality())
.expectComplete()
.verify(Duration.ofMinutes(5));
}
@Test
public void listMembersWithEntity() throws TimeoutException, InterruptedException {
String displayName = this.nameFactory.getGroupName();
String userName = this.nameFactory.getUserName();
createUserId(this.uaaClient, userName)
.then(userId -> createGroupIdWithMember(this.uaaClient, displayName, userId))
.flatMapMany(groupId -> this.uaaClient.groups()
.listMembers(ListMembersRequest.builder()
.groupId(groupId)
.returnEntities(true)
.build()))
.flatMapIterable(ListMembersResponse::getMembers)
.map(Member::getEntity)
.map(Optional::get)
.cast(UserEntity.class)
.single()
.map(UserEntity::getUserName)
.as(StepVerifier::create)
.expectNext(userName)
.expectComplete()
.verify(Duration.ofMinutes(5));
}
@Test
public void mapExternalGroupMappings() {
String displayName = this.nameFactory.getGroupName();
createGroupId(this.uaaClient, displayName)
.then(groupId -> this.uaaClient.groups()
.mapExternalGroup(MapExternalGroupRequest.builder()
.externalGroup(displayName + "-external-group")
.groupId(groupId)
.origin(displayName + "-origin")
.build()))
.thenMany(requestListExternalGroupResource(this.uaaClient)
.filter(group -> displayName.equals(group.getDisplayName())))
.as(StepVerifier::create)
.consumeNextWith(resource -> {
assertThat(resource.getExternalGroup()).isEqualTo(String.format("%s-external-group", displayName));
assertThat(resource.getOrigin()).isEqualTo(String.format("%s-origin", displayName));
})
.expectComplete()
.verify(Duration.ofMinutes(5));
}
@Test
public void removeMember() throws TimeoutException, InterruptedException {
String displayName = this.nameFactory.getGroupName();
String userName = this.nameFactory.getUserName();
createUserId(this.uaaClient, userName)
.then(userId -> Mono.when(
createGroupIdWithMember(this.uaaClient, displayName, userId),
Mono.just(userId)
))
.then(function((groupId, userId) -> Mono.when(
this.uaaClient.groups()
.removeMember(RemoveMemberRequest.builder()
.groupId(groupId)
.memberId(userId)
.build())
.map(RemoveMemberResponse::getMemberId),
Mono.just(userId)
)))
.as(StepVerifier::create)
.consumeNextWith(tupleEquality())
.expectComplete()
.verify(Duration.ofMinutes(5));
}
@Test
public void unmapExternalGroupMappingsByGroupDisplayName() throws TimeoutException, InterruptedException {
String displayName = this.nameFactory.getGroupName();
createGroupId(this.uaaClient, displayName)
.then(groupId -> requestMapExternalGroupResponse(this.uaaClient, displayName, groupId))
.then(this.uaaClient.groups()
.unmapExternalGroupByGroupDisplayName(UnmapExternalGroupByGroupDisplayNameRequest.builder()
.groupDisplayName(displayName)
.externalGroup(displayName + "-external-group")
.origin(displayName + "-origin")
.build()))
.thenMany(requestListExternalGroupResources(this.uaaClient))
.filter(resource -> displayName.equals(resource.getDisplayName()))
.as(StepVerifier::create)
.expectComplete()
.verify(Duration.ofMinutes(5));
}
@Test
public void unmapExternalGroupMappingsByGroupId() throws TimeoutException, InterruptedException {
String displayName = this.nameFactory.getGroupName();
createGroupId(this.uaaClient, displayName)
.as(thenKeep(groupId -> requestMapExternalGroupResponse(this.uaaClient, displayName, groupId)))
.then(groupId -> this.uaaClient.groups()
.unmapExternalGroupByGroupId(UnmapExternalGroupByGroupIdRequest.builder()
.groupId(groupId)
.externalGroup(displayName + "-external-group")
.origin(displayName + "-origin")
.build()))
.thenMany(requestListExternalGroupResources(this.uaaClient)
.filter(resource -> displayName.equals(resource.getDisplayName())))
.as(StepVerifier::create)
.expectComplete()
.verify(Duration.ofMinutes(5));
}
@Test
public void update() throws TimeoutException, InterruptedException {
String baseDisplayName = this.nameFactory.getGroupName();
String newDisplayName = this.nameFactory.getGroupName();
createGroupId(this.uaaClient, baseDisplayName)
.then(groupId -> this.uaaClient.groups()
.update(UpdateGroupRequest.builder()
.displayName(newDisplayName)
.groupId(groupId)
.version("*")
.build()))
.then(requestList(this.uaaClient)
.filter(resource -> newDisplayName.equals(resource.getDisplayName()))
.single())
.as(StepVerifier::create)
.expectNextCount(1)
.expectComplete()
.verify(Duration.ofMinutes(5));
}
private static Mono<String> createGroupId(UaaClient uaaClient, String displayName) {
return requestCreateGroup(uaaClient, displayName)
.map(CreateGroupResponse::getId);
}
private static Mono<String> createGroupIdWithMember(UaaClient uaaClient, String displayName, String userId) {
return requestCreateGroupWithMember(uaaClient, displayName, userId)
.map(CreateGroupResponse::getId);
}
private static Mono<String> createUserId(UaaClient uaaClient, String userName) {
return requestCreateUser(uaaClient, userName)
.map(CreateUserResponse::getId);
}
private static Mono<CreateGroupResponse> requestCreateGroup(UaaClient uaaClient, String displayName) {
return uaaClient.groups()
.create(CreateGroupRequest.builder()
.displayName(displayName)
.build());
}
private static Mono<CreateGroupResponse> requestCreateGroupWithMember(UaaClient uaaClient, String displayName, String userId) {
return uaaClient.groups()
.create(CreateGroupRequest.builder()
.displayName(displayName)
.member(MemberSummary.builder()
.memberId(userId)
.origin("test-origin")
.type(MemberType.USER)
.build())
.build());
}
private static Mono<CreateUserResponse> requestCreateUser(UaaClient uaaClient, String userName) {
return uaaClient.users()
.create(CreateUserRequest.builder()
.email(Email.builder()
.value("test-email")
.primary(true)
.build())
.name(Name.builder()
.familyName("test-family-name")
.givenName("test-given-name")
.build())
.password("test-password")
.userName(userName)
.build());
}
private static Flux<Group> requestList(UaaClient uaaClient) {
return PaginationUtils
.requestUaaResources(startIndex -> uaaClient.groups()
.list(ListGroupsRequest.builder()
.startIndex(startIndex)
.build()));
}
private static Flux<ExternalGroupResource> requestListExternalGroupResource(UaaClient uaaClient) {
return PaginationUtils
.requestUaaResources(startIndex -> uaaClient.groups()
.listExternalGroupMappings(ListExternalGroupMappingsRequest.builder()
.startIndex(startIndex)
.build()));
}
private static Flux<ExternalGroupResource> requestListExternalGroupResources(UaaClient uaaClient) {
return PaginationUtils
.requestUaaResources(startIndex -> uaaClient.groups()
.listExternalGroupMappings(ListExternalGroupMappingsRequest.builder()
.startIndex(startIndex)
.build()));
}
private static Mono<MapExternalGroupResponse> requestMapExternalGroupResponse(UaaClient uaaClient, String displayName, String groupId) {
return uaaClient.groups()
.mapExternalGroup(MapExternalGroupRequest.builder()
.externalGroup(displayName + "-external-group")
.groupId(groupId)
.origin(displayName + "-origin")
.build());
}
}