001/* 002 * Copyright 2024 Vonage 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.vonage.client.users; 017 018import com.vonage.client.DynamicEndpoint; 019import com.vonage.client.HttpWrapper; 020import com.vonage.client.RestEndpoint; 021import com.vonage.client.VonageClient; 022import com.vonage.client.auth.JWTAuthMethod; 023import com.vonage.client.common.HttpMethod; 024import java.util.List; 025import java.util.Objects; 026import java.util.UUID; 027import java.util.function.Function; 028import java.util.stream.Collectors; 029 030/** 031 * A client for talking to the Vonage Users API. The standard way to obtain an instance of 032 * this class is to use {@link VonageClient#getUsersClient()}. 033 */ 034public class UsersClient { 035 final RestEndpoint<ListUsersRequest, ListUsersResponse> listUsers; 036 final RestEndpoint<User, User> createUser; 037 final RestEndpoint<String, User> getUser; 038 final RestEndpoint<User, User> updateUser; 039 final RestEndpoint<String, Void> deleteUser; 040 041 public UsersClient(HttpWrapper wrapper) { 042 @SuppressWarnings("unchecked") 043 final class Endpoint<T, R> extends DynamicEndpoint<T, R> { 044 Endpoint(Function<T, String> pathGetter, HttpMethod method, R... type) { 045 super(DynamicEndpoint.<T, R> builder(type) 046 .responseExceptionType(UsersResponseException.class) 047 .wrapper(wrapper).requestMethod(method).authMethod(JWTAuthMethod.class) 048 .pathGetter((de, req) -> { 049 String base = de.getHttpWrapper().getHttpConfig().getVersionedApiBaseUri("v1"); 050 String path = base + "/users"; 051 if (pathGetter != null) { 052 path += "/" + pathGetter.apply(req); 053 } 054 return path; 055 }) 056 ); 057 } 058 } 059 060 listUsers = new Endpoint<>(null, HttpMethod.GET); 061 createUser = new Endpoint<>(null, HttpMethod.POST); 062 getUser = new Endpoint<>(Function.identity(), HttpMethod.GET); 063 updateUser = new Endpoint<>(User::getId, HttpMethod.PATCH); 064 deleteUser = new Endpoint<>(Function.identity(), HttpMethod.DELETE); 065 } 066 067 private <U extends BaseUser> U validateUser(U request) { 068 return Objects.requireNonNull(request, "User is required."); 069 } 070 071 private String validateUserId(String id) { 072 Objects.requireNonNull(id, "User ID is required."); 073 String prefix = "USR-"; 074 if (!id.startsWith(prefix)) { 075 throw new IllegalArgumentException("Invalid user ID."); 076 } 077 return prefix + UUID.fromString(id.substring(prefix.length())); 078 } 079 080 /** 081 * Create a new user. 082 * 083 * @param user The properties for the user to be created with. 084 * 085 * @return The user which has been created. 086 * 087 * @throws UsersResponseException If there was an error processing the request. 088 */ 089 public User createUser(User user) throws UsersResponseException { 090 return createUser.execute(validateUser(user)); 091 } 092 093 /** 094 * Update an existing user. 095 * 096 * @param userId Unique ID of the user to update. 097 * @param user The properties for the user to be updated with. 098 * 099 * @return The user which has been updated. 100 * 101 * @throws UsersResponseException If there was an error processing the request. 102 */ 103 public User updateUser(String userId, User user) throws UsersResponseException { 104 validateUser(user).id = validateUserId(userId); 105 return updateUser.execute(user); 106 } 107 108 /** 109 * Retrieve a user. 110 * 111 * @param userId Unique ID of the user to retrieve. 112 * 113 * @return The corresponding user. 114 * 115 * @throws UsersResponseException If there was an error processing the request. 116 */ 117 public User getUser(String userId) throws UsersResponseException { 118 return getUser.execute(validateUserId(userId)); 119 } 120 121 /** 122 * Delete a user. 123 * 124 * @param userId Unique ID of the user to delete. 125 * 126 * @throws UsersResponseException If there was an error processing the request. 127 */ 128 public void deleteUser(String userId) throws UsersResponseException { 129 deleteUser.execute(validateUserId(userId)); 130 } 131 132 /** 133 * Lists users in the application based on the filter criteria. 134 * 135 * @param request Optional parameters to customise the search results. 136 * 137 * @return The HAL response containing the users. 138 * 139 * @throws UsersResponseException If there was an error processing the request. 140 */ 141 public ListUsersResponse listUsers(ListUsersRequest request) throws UsersResponseException { 142 return listUsers.execute(request != null ? request : ListUsersRequest.builder().build()); 143 } 144 145 /** 146 * Lists the first 100 users in the application, from newest to oldest. <br> 147 * <b>NOTE: The users returned from this method will only contain the name and ID, not the full record.</b> 148 * 149 * @return The list of available users in creation order. 150 * 151 * @throws UsersResponseException If there was an error processing the request. 152 * 153 * @see #listUsers(ListUsersRequest) 154 */ 155 public List<BaseUser> listUsers() throws UsersResponseException { 156 return listUsers(ListUsersRequest.builder().pageSize(100).build()).getUsers(); 157 } 158 159 /** 160 * Convenience method that uses the metadata from the base user object to obtain all known fields about the user. 161 * 162 * @param minimalUser The user metadata. 163 * 164 * @return A new {@linkplain User} object with all known fields populated. 165 * 166 * @throws UsersResponseException If there was an error processing the request. 167 */ 168 public User getUserDetails(BaseUser minimalUser) { 169 return getUser(validateUser(minimalUser).getId()); 170 } 171 172 /** 173 * Convenience method that uses the metadata from the base users list to obtain all known fields about the users. 174 * You may use this method to convert the minimal data returned from {@link #listUsers()} or 175 * {@link ListUsersResponse#getUsers()} into fully populated records. 176 * 177 * @param minimalUsers The list of users' metadata. 178 * 179 * @return A list of users with all known fields populated in the same encounter order. 180 * 181 * @throws UsersResponseException If there was an error processing the request. 182 */ 183 public List<User> getUserDetails(List<BaseUser> minimalUsers) { 184 return Objects.requireNonNull(minimalUsers, "Users list is required") 185 .stream().map(this::getUserDetails).collect(Collectors.toList()); 186 } 187}