diff --git a/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/client/_ReactorCloudFoundryClient.java b/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/client/_ReactorCloudFoundryClient.java index 7e43bd5820..9f5d542adf 100644 --- a/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/client/_ReactorCloudFoundryClient.java +++ b/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/client/_ReactorCloudFoundryClient.java @@ -74,6 +74,7 @@ import org.cloudfoundry.client.v3.spaces.SpacesV3; import org.cloudfoundry.client.v3.stacks.StacksV3; import org.cloudfoundry.client.v3.tasks.Tasks; +import org.cloudfoundry.client.v3.users.UsersV3; import org.cloudfoundry.reactor.ConnectionContext; import org.cloudfoundry.reactor.TokenProvider; import org.cloudfoundry.reactor.client.v2.applications.ReactorApplicationsV2; @@ -133,6 +134,7 @@ import org.cloudfoundry.reactor.client.v3.spaces.ReactorSpacesV3; import org.cloudfoundry.reactor.client.v3.stacks.ReactorStacksV3; import org.cloudfoundry.reactor.client.v3.tasks.ReactorTasks; +import org.cloudfoundry.reactor.client.v3.users.ReactorUsersV3; import org.immutables.value.Value; import reactor.core.publisher.Mono; @@ -500,6 +502,12 @@ public Users users() { return new ReactorUsers(getConnectionContext(), getRootV2(), getTokenProvider(), getRequestTags()); } + @Override + @Value.Derived + public UsersV3 usersV3() { + return new ReactorUsersV3(getConnectionContext(), getRootV3(), getTokenProvider(), getRequestTags()); + } + /** * The connection context */ diff --git a/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/client/v3/users/ReactorUsersV3.java b/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/client/v3/users/ReactorUsersV3.java new file mode 100644 index 0000000000..2d42f0fff4 --- /dev/null +++ b/cloudfoundry-client-reactor/src/main/java/org/cloudfoundry/reactor/client/v3/users/ReactorUsersV3.java @@ -0,0 +1,83 @@ +/* + * Copyright 2013-2021 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.reactor.client.v3.users; + +import org.cloudfoundry.client.v3.users.*; +import org.cloudfoundry.reactor.ConnectionContext; +import org.cloudfoundry.reactor.TokenProvider; +import org.cloudfoundry.reactor.client.v3.AbstractClientV3Operations; +import reactor.core.publisher.Mono; + +import java.util.Map; + +/** + * The Reactor-based implementation of {@link UsersV3} + */ +public class ReactorUsersV3 extends AbstractClientV3Operations implements UsersV3 { + + /** + * Creates an instance + * + * @param connectionContext the {@link ConnectionContext} to use when communicating with the server + * @param root the root URI of the server. Typically, something like {@code https://api.cloudfoundry.your.company.com}. + * @param tokenProvider the {@link TokenProvider} to use when communicating with the server + * @param requestTags map with custom http headers which will be added to web request + */ + public ReactorUsersV3( + ConnectionContext connectionContext, + Mono root, + TokenProvider tokenProvider, + Map requestTags) { + super(connectionContext, root, tokenProvider, requestTags); + } + + @Override + public Mono create(CreateUserRequest request) { + return post( + request, + CreateUserResponse.class, + builder -> builder.pathSegment("users")) + .checkpoint(); + } + + @Override + public Mono get(GetUserRequest request) { + return get( + request, + GetUserResponse.class, + builder -> builder.pathSegment("users", request.getUserId())) + .checkpoint(); + } + + @Override + public Mono update(UpdateUserRequest request) { + return patch( + request, + UpdateUserResponse.class, + builder -> builder.pathSegment("users", request.getUserId())) + .checkpoint(); + } + + @Override + public Mono delete(DeleteUserRequest request) { + return delete( + request, + Void.class, + builder -> builder.pathSegment("users", request.getUserId())) + .checkpoint(); + } +} \ No newline at end of file diff --git a/cloudfoundry-client-reactor/src/test/java/org/cloudfoundry/reactor/client/v3/users/ReactorUsersTest.java b/cloudfoundry-client-reactor/src/test/java/org/cloudfoundry/reactor/client/v3/users/ReactorUsersTest.java new file mode 100644 index 0000000000..91676e5c71 --- /dev/null +++ b/cloudfoundry-client-reactor/src/test/java/org/cloudfoundry/reactor/client/v3/users/ReactorUsersTest.java @@ -0,0 +1,215 @@ +/* + * Copyright 2013-2021 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.reactor.client.v3.users; + +import org.cloudfoundry.client.v3.Link; +import org.cloudfoundry.client.v3.Metadata; +import org.cloudfoundry.client.v3.users.*; +import org.cloudfoundry.reactor.InteractionContext; +import org.cloudfoundry.reactor.TestRequest; +import org.cloudfoundry.reactor.TestResponse; +import org.cloudfoundry.reactor.client.AbstractClientApiTest; +import org.junit.jupiter.api.Test; +import reactor.test.StepVerifier; + +import java.time.Duration; +import java.util.Collections; +import java.util.Map; + +import static io.netty.handler.codec.http.HttpMethod.*; +import static io.netty.handler.codec.http.HttpResponseStatus.*; + +final class ReactorUsersTest extends AbstractClientApiTest { + private final ReactorUsersV3 users = + new ReactorUsersV3(CONNECTION_CONTEXT, this.root, TOKEN_PROVIDER, Collections.emptyMap()); + + @Test + void create() { + mockRequest( + InteractionContext.builder() + .request( + TestRequest.builder() + .method(POST) + .path("/users") + .payload( + "fixtures/client/v3/users/POST_request.json") + .build()) + .response( + TestResponse.builder() + .status(CREATED) + .payload( + "fixtures/client/v3/users/POST_response.json") + .build()) + .build()); + + this.users + .create(CreateUserRequest.builder() + .userId("3a5d3d89-3f89-4f05-8188-8a2b298c79d5") + .build() + ) + .as(StepVerifier::create) + .expectNext( + CreateUserResponse.builder() + .id("3a5d3d89-3f89-4f05-8188-8a2b298c79d5") + .createdAt("2019-03-08T01:06:19Z") + .updatedAt("2019-03-08T01:06:19Z") + .username("some-name") + .presentationName("some-name") + .origin("uaa") + .metadata( + Metadata.builder() + .putAllAnnotations(Collections.emptyMap()) + .putAllLabels(Collections.emptyMap()) + .build()) + .link( + "self", + Link.builder() + .href( + "https://api.example.org/v3/users/3a5d3d89-3f89-4f05-8188-8a2b298c79d5") + .build()) + .build() + ) + .expectComplete() + .verify(Duration.ofSeconds(5)); + } + + @Test + void get() { + mockRequest( + InteractionContext.builder() + .request( + TestRequest.builder() + .method(GET) + .path("/users/3a5d3d89-3f89-4f05-8188-8a2b298c79d5") + .build()) + .response( + TestResponse.builder() + .status(OK) + .payload( + "fixtures/client/v3/users/GET_{id}_response.json") + .build()) + .build()); + + this.users + .get(GetUserRequest.builder() + .userId("3a5d3d89-3f89-4f05-8188-8a2b298c79d5") + .build() + ) + .as(StepVerifier::create) + .expectNext( + GetUserResponse.builder() + .id("3a5d3d89-3f89-4f05-8188-8a2b298c79d5") + .createdAt("2019-03-08T01:06:19Z") + .updatedAt("2019-03-08T01:06:19Z") + .username("some-name") + .presentationName("some-name") + .origin("uaa") + .metadata( + Metadata.builder() + .putAllAnnotations(Collections.emptyMap()) + .putAllLabels(Collections.emptyMap()) + .build()) + .link( + "self", + Link.builder() + .href( + "https://api.example.org/v3/users/3a5d3d89-3f89-4f05-8188-8a2b298c79d5") + .build()) + .build() + ) + .expectComplete() + .verify(Duration.ofSeconds(5)); + } + + @Test + void update() { + mockRequest( + InteractionContext.builder() + .request( + TestRequest.builder() + .method(PATCH) + .path("/users/3a5d3d89-3f89-4f05-8188-8a2b298c79d5") + .payload( + "fixtures/client/v3/users/PATCH_{id}_request.json") + .build()) + .response( + TestResponse.builder() + .status(CREATED) + .payload( + "fixtures/client/v3/users/PATCH_{id}_response.json") + .build()) + .build()); + + this.users + .update(UpdateUserRequest.builder() + .userId("3a5d3d89-3f89-4f05-8188-8a2b298c79d5") + .metadata(Metadata.builder() + .putAllAnnotations(Map.of("note", "detailed information")) + .putAllLabels(Map.of("environment", "production")) + .build()) + .build() + ) + .as(StepVerifier::create) + .expectNext( + UpdateUserResponse.builder() + .id("3a5d3d89-3f89-4f05-8188-8a2b298c79d5") + .createdAt("2019-03-08T01:06:19Z") + .updatedAt("2019-03-08T01:06:19Z") + .username("some-name") + .presentationName("some-name") + .origin("uaa") + .metadata(Metadata.builder() + .putAllAnnotations(Map.of("note", "detailed information")) + .putAllLabels(Map.of("environment", "production")) + .build()) + .link( + "self", + Link.builder() + .href( + "https://api.example.org/v3/users/3a5d3d89-3f89-4f05-8188-8a2b298c79d5") + .build()) + .build() + ) + .expectComplete() + .verify(Duration.ofSeconds(5)); + } + + @Test + void delete() { + mockRequest( + InteractionContext.builder() + .request( + TestRequest.builder() + .method(DELETE) + .path("/users/3a5d3d89-3f89-4f05-8188-8a2b298c79d5") + .build()) + .response( + TestResponse.builder() + .status(ACCEPTED) + .build()) + .build()); + + this.users + .delete(DeleteUserRequest.builder() + .userId("3a5d3d89-3f89-4f05-8188-8a2b298c79d5") + .build() + ) + .as(StepVerifier::create) + .expectComplete() + .verify(Duration.ofSeconds(5)); + } + +} diff --git a/cloudfoundry-client-reactor/src/test/resources/fixtures/client/v3/users/GET_{id}_response.json b/cloudfoundry-client-reactor/src/test/resources/fixtures/client/v3/users/GET_{id}_response.json new file mode 100644 index 0000000000..b60ce5ab33 --- /dev/null +++ b/cloudfoundry-client-reactor/src/test/resources/fixtures/client/v3/users/GET_{id}_response.json @@ -0,0 +1,17 @@ +{ + "guid": "3a5d3d89-3f89-4f05-8188-8a2b298c79d5", + "created_at": "2019-03-08T01:06:19Z", + "updated_at": "2019-03-08T01:06:19Z", + "username": "some-name", + "presentation_name": "some-name", + "origin": "uaa", + "metadata": { + "labels": {}, + "annotations": {} + }, + "links": { + "self": { + "href": "https://api.example.org/v3/users/3a5d3d89-3f89-4f05-8188-8a2b298c79d5" + } + } +} \ No newline at end of file diff --git a/cloudfoundry-client-reactor/src/test/resources/fixtures/client/v3/users/PATCH_{id}_request.json b/cloudfoundry-client-reactor/src/test/resources/fixtures/client/v3/users/PATCH_{id}_request.json new file mode 100644 index 0000000000..52c4a1b610 --- /dev/null +++ b/cloudfoundry-client-reactor/src/test/resources/fixtures/client/v3/users/PATCH_{id}_request.json @@ -0,0 +1,10 @@ +{ + "metadata": { + "labels": { + "environment": "production" + }, + "annotations": { + "note": "detailed information" + } + } +} \ No newline at end of file diff --git a/cloudfoundry-client-reactor/src/test/resources/fixtures/client/v3/users/PATCH_{id}_response.json b/cloudfoundry-client-reactor/src/test/resources/fixtures/client/v3/users/PATCH_{id}_response.json new file mode 100644 index 0000000000..9275a05c46 --- /dev/null +++ b/cloudfoundry-client-reactor/src/test/resources/fixtures/client/v3/users/PATCH_{id}_response.json @@ -0,0 +1,21 @@ +{ + "guid": "3a5d3d89-3f89-4f05-8188-8a2b298c79d5", + "created_at": "2019-03-08T01:06:19Z", + "updated_at": "2019-03-08T01:06:19Z", + "username": "some-name", + "presentation_name": "some-name", + "origin": "uaa", + "metadata": { + "labels": { + "environment": "production" + }, + "annotations": { + "note": "detailed information" + } + }, + "links": { + "self": { + "href": "https://api.example.org/v3/users/3a5d3d89-3f89-4f05-8188-8a2b298c79d5" + } + } +} diff --git a/cloudfoundry-client-reactor/src/test/resources/fixtures/client/v3/users/POST_request.json b/cloudfoundry-client-reactor/src/test/resources/fixtures/client/v3/users/POST_request.json new file mode 100644 index 0000000000..e5463b4edb --- /dev/null +++ b/cloudfoundry-client-reactor/src/test/resources/fixtures/client/v3/users/POST_request.json @@ -0,0 +1,3 @@ +{ + "guid": "3a5d3d89-3f89-4f05-8188-8a2b298c79d5" +} \ No newline at end of file diff --git a/cloudfoundry-client-reactor/src/test/resources/fixtures/client/v3/users/POST_response.json b/cloudfoundry-client-reactor/src/test/resources/fixtures/client/v3/users/POST_response.json new file mode 100644 index 0000000000..b60ce5ab33 --- /dev/null +++ b/cloudfoundry-client-reactor/src/test/resources/fixtures/client/v3/users/POST_response.json @@ -0,0 +1,17 @@ +{ + "guid": "3a5d3d89-3f89-4f05-8188-8a2b298c79d5", + "created_at": "2019-03-08T01:06:19Z", + "updated_at": "2019-03-08T01:06:19Z", + "username": "some-name", + "presentation_name": "some-name", + "origin": "uaa", + "metadata": { + "labels": {}, + "annotations": {} + }, + "links": { + "self": { + "href": "https://api.example.org/v3/users/3a5d3d89-3f89-4f05-8188-8a2b298c79d5" + } + } +} \ No newline at end of file diff --git a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/CloudFoundryClient.java b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/CloudFoundryClient.java index c229b37230..756fe27814 100644 --- a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/CloudFoundryClient.java +++ b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/CloudFoundryClient.java @@ -73,6 +73,7 @@ import org.cloudfoundry.client.v3.spaces.SpacesV3; import org.cloudfoundry.client.v3.stacks.StacksV3; import org.cloudfoundry.client.v3.tasks.Tasks; +import org.cloudfoundry.client.v3.users.UsersV3; /** * Main entry point to the Cloud Foundry Client API @@ -369,4 +370,9 @@ public interface CloudFoundryClient { * Main entry point to the Cloud Foundry Users Client API */ Users users(); + + /** + * Main entry point to the Cloud Foundry Users Client API + */ + UsersV3 usersV3(); } diff --git a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/User.java b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/User.java new file mode 100644 index 0000000000..9f60d78b49 --- /dev/null +++ b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/User.java @@ -0,0 +1,55 @@ +/* + * Copyright 2013-2021 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.client.v3.users; + +import com.fasterxml.jackson.annotation.JsonProperty; +import org.cloudfoundry.Nullable; +import org.cloudfoundry.client.v3.Metadata; +import org.cloudfoundry.client.v3.Resource; + +/** + * Base class for responses that are users + */ +public abstract class User extends Resource { + + /** + * The username + */ + @JsonProperty("username") + @Nullable + public abstract String getUsername(); + + /** + * The presentation name + */ + @JsonProperty("presentation_name") + @Nullable + public abstract String getPresentationName(); + + /** + * The origin + */ + @JsonProperty("origin") + @Nullable + public abstract String getOrigin(); + + /** + * The metadata + */ + @JsonProperty("metadata") + @Nullable + public abstract Metadata getMetadata(); +} diff --git a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/UsersV3.java b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/UsersV3.java new file mode 100644 index 0000000000..574fd48cb3 --- /dev/null +++ b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/UsersV3.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013-2021 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.client.v3.users; + + +import reactor.core.publisher.Mono; + + +/** + * Main entry point to the Cloud Foundry Users V3 Client API + */ +public interface UsersV3 { + + /** + * Makes the Create a User request + * + * @param request the Create User request + * @return the response from the Create User request + */ + Mono create(CreateUserRequest request); + + /** + * Makes the Get a User request + * + * @param request the Get User request + * @return the response from the Get User request + */ + Mono get(GetUserRequest request); + + /** + * Makes the Update a Stack request + * + * @param request the Update User request + * @return the response from the Update User request + */ + Mono update(UpdateUserRequest request); + + /** + * Makes the Delete a User request + * + * @param request the Delete User request + * @return void + */ + Mono delete(DeleteUserRequest request); +} \ No newline at end of file diff --git a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_CreateUserRequest.java b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_CreateUserRequest.java new file mode 100644 index 0000000000..aaa9a537a9 --- /dev/null +++ b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_CreateUserRequest.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013-2021 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.client.v3.users; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.cloudfoundry.Nullable; +import org.cloudfoundry.client.v3.Metadata; +import org.immutables.value.Value; + +/** + * The request payload for the Create User operation + */ +@JsonSerialize +@Value.Immutable +abstract class _CreateUserRequest { + + /** + * The user id + */ + @JsonProperty("guid") + @Nullable + abstract String getUserId(); + + /** + * The username + */ + @JsonProperty("username") + @Nullable + abstract String getUsername(); + + /** + * The origin + */ + @JsonProperty("origin") + @Nullable + abstract String getOrigin(); + + /** + * The metadata + */ + @JsonProperty("metadata") + @Nullable + abstract Metadata getMetadata(); +} \ No newline at end of file diff --git a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_CreateUserResponse.java b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_CreateUserResponse.java new file mode 100644 index 0000000000..2109e2526e --- /dev/null +++ b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_CreateUserResponse.java @@ -0,0 +1,27 @@ +/* + * Copyright 2013-2021 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.client.v3.users; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.immutables.value.Value; + +/** + * The response payload for the Create Stack operation + */ +@JsonDeserialize +@Value.Immutable +abstract class _CreateUserResponse extends User { +} diff --git a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_DeleteUserRequest.java b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_DeleteUserRequest.java new file mode 100644 index 0000000000..1ce5d06c78 --- /dev/null +++ b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_DeleteUserRequest.java @@ -0,0 +1,33 @@ +/* + * Copyright 2013-2021 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.client.v3.users; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.immutables.value.Value; + +/** + * The request payload for the Delete User operation + */ +@Value.Immutable +abstract class _DeleteUserRequest { + + /** + * The User id + */ + @JsonIgnore + abstract String getUserId(); + +} diff --git a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_GetUserRequest.java b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_GetUserRequest.java new file mode 100644 index 0000000000..6354513615 --- /dev/null +++ b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_GetUserRequest.java @@ -0,0 +1,33 @@ +/* + * Copyright 2013-2021 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.client.v3.users; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.immutables.value.Value; + +/** + * The request payload for the Get User operation + */ +@Value.Immutable +abstract class _GetUserRequest { + + /** + * The user id + */ + @JsonIgnore + abstract String getUserId(); + +} diff --git a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_GetUserResponse.java b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_GetUserResponse.java new file mode 100644 index 0000000000..3d7258aaee --- /dev/null +++ b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_GetUserResponse.java @@ -0,0 +1,28 @@ +/* + * Copyright 2013-2021 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.client.v3.users; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.immutables.value.Value; + +/** + * The response payload for the Get User operation + */ +@JsonDeserialize +@Value.Immutable +abstract class _GetUserResponse extends User { +} + diff --git a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_UpdateUserRequest.java b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_UpdateUserRequest.java new file mode 100644 index 0000000000..2d959eb48d --- /dev/null +++ b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_UpdateUserRequest.java @@ -0,0 +1,45 @@ +/* + * Copyright 2013-2021 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.client.v3.users; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.cloudfoundry.Nullable; +import org.cloudfoundry.client.v3.Metadata; +import org.immutables.value.Value; + +/** + * The request payload for the Update User operation + */ +@JsonSerialize +@Value.Immutable +abstract class _UpdateUserRequest { + + /** + * The stack id + */ + @JsonIgnore + abstract String getUserId(); + + /** + * The metadata + */ + @JsonProperty("metadata") + @Nullable + abstract Metadata getMetadata(); + +} \ No newline at end of file diff --git a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_UpdateUserResponse.java b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_UpdateUserResponse.java new file mode 100644 index 0000000000..11fee6b6d1 --- /dev/null +++ b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_UpdateUserResponse.java @@ -0,0 +1,27 @@ +/* + * Copyright 2013-2021 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.client.v3.users; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.immutables.value.Value; + +/** + * The response payload for the Update User operation + */ +@JsonDeserialize +@Value.Immutable +abstract class _UpdateUserResponse extends User { +} \ No newline at end of file diff --git a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_UserResource.java b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_UserResource.java new file mode 100644 index 0000000000..1ab8203e60 --- /dev/null +++ b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/users/_UserResource.java @@ -0,0 +1,27 @@ +/* + * Copyright 2013-2021 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.client.v3.users; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.immutables.value.Value; + +/** + * The Resource response payload for the List Organizations operation + */ +@JsonDeserialize +@Value.Immutable +abstract class _UserResource extends User { +} diff --git a/cloudfoundry-client/src/main/java/org/cloudfoundry/uaa/tokens/GrantType.java b/cloudfoundry-client/src/main/java/org/cloudfoundry/uaa/tokens/GrantType.java index 6dd626c52d..1e9eb36cc4 100644 --- a/cloudfoundry-client/src/main/java/org/cloudfoundry/uaa/tokens/GrantType.java +++ b/cloudfoundry-client/src/main/java/org/cloudfoundry/uaa/tokens/GrantType.java @@ -47,7 +47,22 @@ public enum GrantType { /** * The refresh token grant type */ - REFRESH_TOKEN("refresh_token"); + REFRESH_TOKEN("refresh_token"), + + /** + * The jwt-bearer token grant type + */ + JWT_BEARER("urn:ietf:params:oauth:grant-type:jwt-bearer"), + + /** + * The saml2-bearer token grant type + */ + SAML2_BEARER("urn:ietf:params:oauth:grant-type:saml2-bearer"), + + /** + * The user token token grant type + */ + USER_TOKEN("user_token"); private final String value; @@ -68,6 +83,12 @@ public static GrantType from(String s) { return PASSWORD; case "refresh_token": return REFRESH_TOKEN; + case "urn:ietf:params:oauth:grant-type:jwt-bearer": + return JWT_BEARER; + case "urn:ietf:params:oauth:grant-type:saml2-bearer": + return SAML2_BEARER; + case "user_token": + return USER_TOKEN; default: throw new IllegalArgumentException(String.format("Unknown grant type: %s", s)); } diff --git a/cloudfoundry-client/src/test/java/org/cloudfoundry/client/v3/users/CreateUserRequestTest.java b/cloudfoundry-client/src/test/java/org/cloudfoundry/client/v3/users/CreateUserRequestTest.java new file mode 100644 index 0000000000..b6c22e1650 --- /dev/null +++ b/cloudfoundry-client/src/test/java/org/cloudfoundry/client/v3/users/CreateUserRequestTest.java @@ -0,0 +1,25 @@ +/* + * Copyright 2013-2021 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.client.v3.users; + +import org.junit.jupiter.api.Test; + +class CreateUserRequestTest { + @Test + void valid() { + CreateUserRequest.builder().userId("test-user-id").build(); + } +} diff --git a/cloudfoundry-client/src/test/java/org/cloudfoundry/client/v3/users/DeleteUserRequestTest.java b/cloudfoundry-client/src/test/java/org/cloudfoundry/client/v3/users/DeleteUserRequestTest.java new file mode 100644 index 0000000000..23ee0e0ea5 --- /dev/null +++ b/cloudfoundry-client/src/test/java/org/cloudfoundry/client/v3/users/DeleteUserRequestTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013-2021 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.client.v3.users; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class DeleteUserRequestTest { + + @Test + void noUserId() { + assertThrows( + IllegalStateException.class, + () -> DeleteUserRequest.builder().build()); + } + + @Test + void valid() { + DeleteUserRequest.builder().userId("test-stack-id").build(); + } +} diff --git a/cloudfoundry-client/src/test/java/org/cloudfoundry/client/v3/users/GetUserRequestTest.java b/cloudfoundry-client/src/test/java/org/cloudfoundry/client/v3/users/GetUserRequestTest.java new file mode 100644 index 0000000000..4b353ec495 --- /dev/null +++ b/cloudfoundry-client/src/test/java/org/cloudfoundry/client/v3/users/GetUserRequestTest.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013-2021 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.client.v3.users; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +class GetUserRequestTest { + + @Test + void noUserId() { + assertThrows( + IllegalStateException.class, + () -> GetUserRequest.builder().build()); + } + + @Test + void valid() { + GetUserRequest.builder() + .userId("test-user-id") + .build(); + } +} + diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v3/UsersTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v3/UsersTest.java new file mode 100644 index 0000000000..1dbdfa336d --- /dev/null +++ b/integration-test/src/test/java/org/cloudfoundry/client/v3/UsersTest.java @@ -0,0 +1,138 @@ +/* + * Copyright 2013-2021 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.client.v3; + + +import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.CloudFoundryVersion; +import org.cloudfoundry.IfCloudFoundryVersion; +import org.cloudfoundry.client.CloudFoundryClient; +import org.cloudfoundry.client.v3.users.*; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +import java.time.Duration; + +import static org.assertj.core.api.Assertions.assertThat; + +@IfCloudFoundryVersion(greaterThanOrEqualTo = CloudFoundryVersion.PCF_4_v3) +public final class UsersTest extends AbstractIntegrationTest { + + @Autowired + private CloudFoundryClient cloudFoundryClient; + + private static Mono createUser( + CloudFoundryClient cloudFoundryClient, String userId) { + return cloudFoundryClient + .usersV3() + .create(CreateUserRequest.builder().userId(userId).build()); + } + + private static Mono getUser( + CloudFoundryClient cloudFoundryClient, String userId) { + return cloudFoundryClient + .usersV3() + .get(GetUserRequest.builder().userId(userId).build()); + } + + @Test + public void create() { + String userId = this.nameFactory.getUserId(); + + this.cloudFoundryClient + .usersV3() + .create(CreateUserRequest.builder() + .userId(userId) + .build() + ) + .single() + .as(StepVerifier::create) + .expectNextCount(1) + .expectComplete() + .verify(Duration.ofMinutes(5)); + } + + @Test + public void get() { + String userId = this.nameFactory.getUserId(); + + createUser(this.cloudFoundryClient, userId) + .flatMap(createUserResponse -> + this.cloudFoundryClient.usersV3() + .get(GetUserRequest.builder() + .userId(userId) + .build())) + .map(GetUserResponse::getId) + .as(StepVerifier::create) + .expectNext(userId) + .expectComplete() + .verify(Duration.ofMinutes(5)); + } + + @Test + public void update() { + String userId = this.nameFactory.getUserId(); + + createUser(this.cloudFoundryClient, userId) + .flatMap(createUserResponse -> + this.cloudFoundryClient.usersV3() + .update(UpdateUserRequest.builder() + .userId(userId) + .metadata(Metadata.builder() + .annotation( + "annotationKey", + "annotationValue") + .label( + "labelKey", + "labelValue") + .build()) + .build())) + .then(getUser(cloudFoundryClient, userId)) + .as(StepVerifier::create) + .consumeNextWith( + GetUserResponse -> { + Metadata metadata = GetUserResponse.getMetadata(); + assertThat(metadata.getAnnotations().get("annotationKey")) + .isEqualTo("annotationValue"); + assertThat(metadata.getLabels().get("labelKey")) + .isEqualTo("labelValue"); + }) + .expectComplete() + .verify(Duration.ofMinutes(5)); + + } + + @Test + public void delete() { + String userId = this.nameFactory.getUserId(); + + createUser(this.cloudFoundryClient, userId) + .flatMap( + createUserResponse -> + this.cloudFoundryClient + .usersV3() + .delete( + DeleteUserRequest.builder() + .userId(createUserResponse.getId()) + .build())) + .as(StepVerifier::create) + .expectComplete() + .verify(Duration.ofMinutes(5)); + } +}