001package com.box.sdk; 002 003import java.io.InputStream; 004import java.net.URL; 005import java.util.ArrayList; 006import java.util.Collection; 007import java.util.HashMap; 008import java.util.Iterator; 009import java.util.List; 010import java.util.Map; 011 012import com.eclipsesource.json.JsonArray; 013import com.eclipsesource.json.JsonObject; 014import com.eclipsesource.json.JsonValue; 015 016/** 017 * Represents a Box user account. 018 * 019 * <p>Unless otherwise noted, the methods in this class can throw an unchecked {@link BoxAPIException} (unchecked 020 * meaning that the compiler won't force you to handle it) if an error occurs. If you wish to implement custom error 021 * handling for errors related to the Box REST API, you should capture this exception explicitly.</p> 022 */ 023@BoxResourceType("user") 024public class BoxUser extends BoxCollaborator { 025 026 /** 027 * An array of all possible file fields that can be requested when calling {@link #getInfo(String...)}. 028 */ 029 public static final String[] ALL_FIELDS = {"type", "id", "name", "login", "created_at", "modified_at", "role", 030 "language", "timezone", "space_amount", "space_used", "max_upload_size", "tracking_codes", 031 "can_see_managed_users", "is_sync_enabled", "is_external_collab_restricted", "status", "job_title", "phone", 032 "address", "avatar_url", "is_exempt_from_device_limits", "is_exempt_from_login_verification", "enterprise", 033 "my_tags", "hostname", "is_platform_access_only", "external_app_user_id"}; 034 035 /** 036 * User URL Template. 037 */ 038 public static final URLTemplate USER_URL_TEMPLATE = new URLTemplate("users/%s"); 039 /** 040 * Get Me URL Template. 041 */ 042 public static final URLTemplate GET_ME_URL = new URLTemplate("users/me"); 043 /** 044 * Users URL Template. 045 */ 046 public static final URLTemplate USERS_URL_TEMPLATE = new URLTemplate("users"); 047 /** 048 * User Memberships URL Template. 049 */ 050 public static final URLTemplate USER_MEMBERSHIPS_URL_TEMPLATE = new URLTemplate("users/%s/memberships"); 051 /** 052 * E-Mail Alias URL Template. 053 */ 054 public static final URLTemplate EMAIL_ALIAS_URL_TEMPLATE = new URLTemplate("users/%s/email_aliases/%s"); 055 /** 056 * E-Mail Aliases URL Template. 057 */ 058 public static final URLTemplate EMAIL_ALIASES_URL_TEMPLATE = new URLTemplate("users/%s/email_aliases"); 059 /** 060 * Move Folder To User Template. 061 */ 062 public static final URLTemplate MOVE_FOLDER_TO_USER_TEMPLATE = new URLTemplate("users/%s/folders/%s"); 063 /** 064 * User Avatar Template. 065 */ 066 public static final URLTemplate USER_AVATAR_TEMPLATE = new URLTemplate("users/%s/avatar"); 067 068 /** 069 * Constructs a BoxUser for a user with a given ID. 070 * @param api the API connection to be used by the user. 071 * @param id the ID of the user. 072 */ 073 public BoxUser(BoxAPIConnection api, String id) { 074 super(api, id); 075 } 076 077 /** 078 * Provisions a new app user in an enterprise using Box Developer Edition. 079 * @param api the API connection to be used by the created user. 080 * @param name the name of the user. 081 * @return the created user's info. 082 */ 083 public static BoxUser.Info createAppUser(BoxAPIConnection api, String name) { 084 return createAppUser(api, name, new CreateUserParams()); 085 } 086 087 /** 088 * Provisions a new app user in an enterprise with additional user information using Box Developer Edition. 089 * @param api the API connection to be used by the created user. 090 * @param name the name of the user. 091 * @param params additional user information. 092 * @return the created user's info. 093 */ 094 public static BoxUser.Info createAppUser(BoxAPIConnection api, String name, 095 CreateUserParams params) { 096 097 params.setIsPlatformAccessOnly(true); 098 return createEnterpriseUser(api, null, name, params); 099 } 100 101 /** 102 * Provisions a new user in an enterprise. 103 * @param api the API connection to be used by the created user. 104 * @param login the email address the user will use to login. 105 * @param name the name of the user. 106 * @return the created user's info. 107 */ 108 public static BoxUser.Info createEnterpriseUser(BoxAPIConnection api, String login, String name) { 109 return createEnterpriseUser(api, login, name, null); 110 } 111 112 /** 113 * Provisions a new user in an enterprise with additional user information. 114 * @param api the API connection to be used by the created user. 115 * @param login the email address the user will use to login. 116 * @param name the name of the user. 117 * @param params additional user information. 118 * @return the created user's info. 119 */ 120 public static BoxUser.Info createEnterpriseUser(BoxAPIConnection api, String login, String name, 121 CreateUserParams params) { 122 123 JsonObject requestJSON = new JsonObject(); 124 requestJSON.add("login", login); 125 requestJSON.add("name", name); 126 127 if (params != null) { 128 if (params.getRole() != null) { 129 requestJSON.add("role", params.getRole().toJSONValue()); 130 } 131 132 if (params.getStatus() != null) { 133 requestJSON.add("status", params.getStatus().toJSONValue()); 134 } 135 136 requestJSON.add("language", params.getLanguage()); 137 requestJSON.add("is_sync_enabled", params.getIsSyncEnabled()); 138 requestJSON.add("job_title", params.getJobTitle()); 139 requestJSON.add("phone", params.getPhone()); 140 requestJSON.add("address", params.getAddress()); 141 requestJSON.add("space_amount", params.getSpaceAmount()); 142 requestJSON.add("can_see_managed_users", params.getCanSeeManagedUsers()); 143 requestJSON.add("timezone", params.getTimezone()); 144 requestJSON.add("is_exempt_from_device_limits", params.getIsExemptFromDeviceLimits()); 145 requestJSON.add("is_exempt_from_login_verification", params.getIsExemptFromLoginVerification()); 146 requestJSON.add("is_platform_access_only", params.getIsPlatformAccessOnly()); 147 requestJSON.add("external_app_user_id", params.getExternalAppUserId()); 148 requestJSON.add("is_external_collab_restricted", params.getIsExternalCollabRestricted()); 149 } 150 151 URL url = USERS_URL_TEMPLATE.build(api.getBaseURL()); 152 BoxJSONRequest request = new BoxJSONRequest(api, url, "POST"); 153 request.setBody(requestJSON.toString()); 154 BoxJSONResponse response = (BoxJSONResponse) request.send(); 155 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 156 157 BoxUser createdUser = new BoxUser(api, responseJSON.get("id").asString()); 158 return createdUser.new Info(responseJSON); 159 } 160 161 /** 162 * Gets the current user. 163 * @param api the API connection of the current user. 164 * @return the current user. 165 */ 166 public static BoxUser getCurrentUser(BoxAPIConnection api) { 167 URL url = GET_ME_URL.build(api.getBaseURL()); 168 BoxAPIRequest request = new BoxAPIRequest(api, url, "GET"); 169 BoxJSONResponse response = (BoxJSONResponse) request.send(); 170 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 171 return new BoxUser(api, jsonObject.get("id").asString()); 172 } 173 174 /** 175 * Returns an iterable containing all the enterprise users. 176 * @param api the API connection to be used when retrieving the users. 177 * @return an iterable containing all the enterprise users. 178 */ 179 public static Iterable<BoxUser.Info> getAllEnterpriseUsers(final BoxAPIConnection api) { 180 return getAllEnterpriseUsers(api, false, null); 181 } 182 183 184 /** 185 * Returns an iterable containing all the enterprise users. Uses marker based pagination. 186 * @param api the API connection to be used when retrieving the users. 187 * @param usemarker Boolean that determines whether to use marker based pagination. 188 * @param marker The marker at which the iterator will begin. 189 * @return an iterable containing all the enterprise users. 190 */ 191 public static Iterable<BoxUser.Info> getAllEnterpriseUsers(final BoxAPIConnection api, final boolean usemarker, 192 final String marker) { 193 return getUsersInfoForType(api, null, null, null, usemarker, marker); 194 } 195 196 /** 197 * Returns an iterable containing all the enterprise users that matches the filter and specifies which child fields 198 * to retrieve from the API. 199 * @param api the API connection to be used when retrieving the users. 200 * @param filterTerm used to filter the results to only users starting with this string in either the name or the 201 * login. Can be null to not filter the results. 202 * @param fields the fields to retrieve. Leave this out for the standard fields. 203 * @return an iterable containing all the enterprise users that matches the filter. 204 */ 205 public static Iterable<BoxUser.Info> getAllEnterpriseUsers(final BoxAPIConnection api, final String filterTerm, 206 final String... fields) { 207 return getUsersInfoForType(api, filterTerm, null, null, false, null, fields); 208 } 209 210 /** 211 * Returns an iterable containing all the enterprise users that matches the filter and specifies which child fields 212 * to retrieve from the API. Uses marker based pagination. 213 * @param api the API connection to be used when retrieving the users. 214 * @param filterTerm used to filter the results to only users starting with this string in either the name or the 215 * login. Can be null to not filter the results. 216 * @param usemarker Boolean that determines whether to use marker based pagination. 217 * @param marker The marker at which the iterator will begin. 218 * @param fields the fields to retrieve. Leave this out for the standard fields. 219 * @return an iterable containing all the enterprise users that matches the filter. 220 */ 221 public static Iterable<BoxUser.Info> getAllEnterpriseUsers(final BoxAPIConnection api, final String filterTerm, 222 final boolean usemarker, final String marker, final String... fields) { 223 return getUsersInfoForType(api, filterTerm, null, null, usemarker, marker, fields); 224 } 225 226 /** 227 * Gets a limited set of information about an external user. (A user collaborating 228 * on content owned by the enterprise). Note: Only fields the user has permission to 229 * see will be returned with values. Other fields will return a value of null. 230 * @param api the API connection to be used when retrieving the users. 231 * @param filterTerm used to filter the results to only users matching the given login. 232 * This does exact match only, so if no filter term is passed in, nothing 233 * will be returned. 234 * @param fields the fields to retrieve. Leave this out for the standard fields. 235 * @return an iterable containing external users matching the given email 236 */ 237 public static Iterable<BoxUser.Info> getExternalUsers(final BoxAPIConnection api, final String filterTerm, 238 final String... fields) { 239 return getUsersInfoForType(api, filterTerm, "external", null, false, null, fields); 240 } 241 242 /** 243 * Gets a limited set of information about an external user. (A user collaborating 244 * on content owned by the enterprise). Note: Only fields the user has permission to 245 * see will be returned with values. Other fields will return a value of null. Uses marker based pagination. 246 * @param api the API connection to be used when retrieving the users. 247 * @param filterTerm used to filter the results to only users matching the given login. 248 * This does exact match only, so if no filter term is passed in, nothing 249 * will be returned. 250 * @param usemarker Boolean that determines whether to use marker based pagination. 251 * @param marker The marker at which the iterator will begin. 252 * @param fields the fields to retrieve. Leave this out for the standard fields. 253 * @return an iterable containing external users matching the given email 254 */ 255 public static Iterable<BoxUser.Info> getExternalUsers(final BoxAPIConnection api, final String filterTerm, 256 final boolean usemarker, final String marker, final String... fields) { 257 return getUsersInfoForType(api, filterTerm, "external", null, usemarker, marker, fields); 258 } 259 260 /** 261 * Gets any managed users that match the filter term as well as any external users that 262 * match the filter term. For managed users it matches any users names or emails that 263 * start with the term. For external, it only does full match on email. This method 264 * is ideal to use in the case where you have a full email for a user and you don't 265 * know if they're managed or external. 266 * @param api the API connection to be used when retrieving the users. 267 * @param filterTerm The filter term to lookup users by (login for external, login or name for managed) 268 * @param fields the fields to retrieve. Leave this out for the standard fields. 269 * @return an iterable containing users matching the given email 270 */ 271 public static Iterable<BoxUser.Info> getAllEnterpriseOrExternalUsers(final BoxAPIConnection api, 272 final String filterTerm, final String... fields) { 273 return getUsersInfoForType(api, filterTerm, "all", null, false, null, fields); 274 } 275 276 /** 277 * Gets any managed users that match the filter term as well as any external users that 278 * match the filter term. For managed users it matches any users names or emails that 279 * start with the term. For external, it only does full match on email. This method 280 * is ideal to use in the case where you have a full email for a user and you don't 281 * know if they're managed or external. Uses marker based pagination. 282 * @param api the API connection to be used when retrieving the users. 283 * @param filterTerm The filter term to lookup users by (login for external, login or name for managed) 284 * @param usemarker Boolean that determines whether to use marker based pagination. 285 * @param marker The marker at which the iterator will begin. 286 * @param fields the fields to retrieve. Leave this out for the standard fields. 287 * @return an iterable containing users matching the given email 288 */ 289 public static Iterable<BoxUser.Info> getAllEnterpriseOrExternalUsers(final BoxAPIConnection api, 290 final String filterTerm, final boolean usemarker, final String marker, final String... fields) { 291 return getUsersInfoForType(api, filterTerm, "all", null, usemarker, marker, fields); 292 } 293 294 /** 295 * Gets any app users that has an exact match with the externalAppUserId term. 296 * @param api the API connection to be used when retrieving the users. 297 * @param externalAppUserId the external app user id that has been set for app user 298 * @param fields the fields to retrieve. Leave this out for the standard fields. 299 * @return an iterable containing users matching the given email 300 */ 301 public static Iterable<BoxUser.Info> getAppUsersByExternalAppUserID(final BoxAPIConnection api, 302 final String externalAppUserId, final String... fields) { 303 return getUsersInfoForType(api, null, null, externalAppUserId, false, null, fields); 304 } 305 306 /** 307 * Gets any app users that has an exact match with the externalAppUserId term using marker based pagination. 308 * @param api the API connection to be used when retrieving the users. 309 * @param externalAppUserId the external app user id that has been set for app user 310 * @param usemarker Boolean that determines whether to use marker based pagination. 311 * @param marker The marker at which the iterator will begin. 312 * @param fields the fields to retrieve. Leave this out for the standard fields. 313 * @return an iterable containing users matching the given email 314 */ 315 public static Iterable<BoxUser.Info> getAppUsersByExternalAppUserID(final BoxAPIConnection api, 316 final String externalAppUserId, final boolean usemarker, String marker, final String... fields) { 317 return getUsersInfoForType(api, null, null, externalAppUserId, usemarker, marker, fields); 318 } 319 320 /** 321 * Helper method to abstract out the common logic from the various users methods. 322 * 323 * @param api the API connection to be used when retrieving the users. 324 * @param filterTerm The filter term to lookup users by (login for external, login or name for managed) 325 * @param userType The type of users we want to search with this request. 326 * Valid values are 'managed' (enterprise users), 'external' or 'all' 327 * @param externalAppUserId the external app user id that has been set for an app user 328 * @param usemarker Boolean that determines whether to use marker based pagination. 329 * @param marker The marker at which the iterator will begin. 330 * @param fields the fields to retrieve. Leave this out for the standard fields. 331 * @return An iterator over the selected users. 332 */ 333 private static Iterable<BoxUser.Info> getUsersInfoForType(final BoxAPIConnection api, final String filterTerm, 334 final String userType, final String externalAppUserId, final boolean usemarker, final String marker, 335 final String... fields) { 336 337 final QueryStringBuilder builder = new QueryStringBuilder(); 338 if (filterTerm != null) { 339 builder.appendParam("filter_term", filterTerm); 340 } 341 if (userType != null) { 342 builder.appendParam("user_type", userType); 343 } 344 if (externalAppUserId != null) { 345 builder.appendParam("external_app_user_id", externalAppUserId); 346 } 347 if (usemarker) { 348 builder.appendParam("usemarker", "true"); 349 } 350 if (fields.length > 0) { 351 builder.appendParam("fields", fields); 352 } 353 final URL url = USERS_URL_TEMPLATE.buildWithQuery(api.getBaseURL(), builder.toString()); 354 355 if (usemarker) { 356 return new BoxResourceIterable<BoxUser.Info>(api, url, 100, null, marker) { 357 @Override 358 protected BoxUser.Info factory(JsonObject jsonObject) { 359 BoxUser user = new BoxUser(api, jsonObject.get("id").asString()); 360 return user.new Info(jsonObject); 361 } 362 }; 363 } else { 364 return new Iterable<BoxUser.Info>() { 365 public Iterator<BoxUser.Info> iterator() { 366 return new BoxUserIterator(api, url); 367 } 368 }; 369 } 370 } 371 372 /** 373 * Gets information about this user. 374 * @param fields the optional fields to retrieve. 375 * @return info about this user. 376 */ 377 public BoxUser.Info getInfo(String... fields) { 378 URL url; 379 if (fields.length > 0) { 380 String queryString = new QueryStringBuilder().appendParam("fields", fields).toString(); 381 url = USER_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID()); 382 } else { 383 url = USER_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 384 } 385 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 386 BoxJSONResponse response = (BoxJSONResponse) request.send(); 387 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 388 return new Info(jsonObject); 389 } 390 391 /** 392 * Gets information about all of the group memberships for this user. 393 * Does not support paging. 394 * 395 * <p>Note: This method is only available to enterprise admins.</p> 396 * 397 * @return a collection of information about the group memberships for this user. 398 */ 399 public Collection<BoxGroupMembership.Info> getMemberships() { 400 BoxAPIConnection api = this.getAPI(); 401 URL url = USER_MEMBERSHIPS_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 402 403 BoxAPIRequest request = new BoxAPIRequest(api, url, "GET"); 404 BoxJSONResponse response = (BoxJSONResponse) request.send(); 405 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 406 407 int entriesCount = responseJSON.get("total_count").asInt(); 408 Collection<BoxGroupMembership.Info> memberships = new ArrayList<BoxGroupMembership.Info>(entriesCount); 409 JsonArray entries = responseJSON.get("entries").asArray(); 410 for (JsonValue entry : entries) { 411 JsonObject entryObject = entry.asObject(); 412 BoxGroupMembership membership = new BoxGroupMembership(api, entryObject.get("id").asString()); 413 BoxGroupMembership.Info info = membership.new Info(entryObject); 414 memberships.add(info); 415 } 416 417 return memberships; 418 } 419 420 /** 421 * Gets information about all of the group memberships for this user as iterable with paging support. 422 * @param fields the fields to retrieve. 423 * @return an iterable with information about the group memberships for this user. 424 */ 425 public Iterable<BoxGroupMembership.Info> getAllMemberships(String ... fields) { 426 final QueryStringBuilder builder = new QueryStringBuilder(); 427 if (fields.length > 0) { 428 builder.appendParam("fields", fields); 429 } 430 return new Iterable<BoxGroupMembership.Info>() { 431 public Iterator<BoxGroupMembership.Info> iterator() { 432 URL url = USER_MEMBERSHIPS_URL_TEMPLATE.buildWithQuery( 433 BoxUser.this.getAPI().getBaseURL(), builder.toString(), BoxUser.this.getID()); 434 return new BoxGroupMembershipIterator(BoxUser.this.getAPI(), url); 435 } 436 }; 437 } 438 439 /** 440 * Adds a new email alias to this user's account. 441 * @param email the email address to add as an alias. 442 * @return the newly created email alias. 443 */ 444 public EmailAlias addEmailAlias(String email) { 445 return this.addEmailAlias(email, false); 446 } 447 448 /** 449 * Adds a new email alias to this user's account and confirms it without user interaction. 450 * This functionality is only available for enterprise admins. 451 * @param email the email address to add as an alias. 452 * @param isConfirmed whether or not the email alias should be automatically confirmed. 453 * @return the newly created email alias. 454 */ 455 public EmailAlias addEmailAlias(String email, boolean isConfirmed) { 456 URL url = EMAIL_ALIASES_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 457 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST"); 458 459 JsonObject requestJSON = new JsonObject() 460 .add("email", email); 461 462 if (isConfirmed) { 463 requestJSON.add("is_confirmed", isConfirmed); 464 } 465 466 request.setBody(requestJSON.toString()); 467 BoxJSONResponse response = (BoxJSONResponse) request.send(); 468 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 469 return new EmailAlias(responseJSON); 470 } 471 472 /** 473 * Deletes an email alias from this user's account. 474 * 475 * <p>The IDs of the user's email aliases can be found by calling {@link #getEmailAliases}.</p> 476 * 477 * @param emailAliasID the ID of the email alias to delete. 478 */ 479 public void deleteEmailAlias(String emailAliasID) { 480 URL url = EMAIL_ALIAS_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), emailAliasID); 481 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE"); 482 BoxAPIResponse response = request.send(); 483 response.disconnect(); 484 } 485 486 /** 487 * Gets a collection of all the email aliases for this user. 488 * 489 * <p>Note that the user's primary login email is not included in the collection of email aliases.</p> 490 * 491 * @return a collection of all the email aliases for this user. 492 */ 493 public Collection<EmailAlias> getEmailAliases() { 494 URL url = EMAIL_ALIASES_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 495 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 496 BoxJSONResponse response = (BoxJSONResponse) request.send(); 497 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 498 499 int totalCount = responseJSON.get("total_count").asInt(); 500 Collection<EmailAlias> emailAliases = new ArrayList<EmailAlias>(totalCount); 501 JsonArray entries = responseJSON.get("entries").asArray(); 502 for (JsonValue value : entries) { 503 JsonObject emailAliasJSON = value.asObject(); 504 emailAliases.add(new EmailAlias(emailAliasJSON)); 505 } 506 507 return emailAliases; 508 } 509 510 /** 511 * Deletes a user from an enterprise account. 512 * @param notifyUser whether or not to send an email notification to the user that their account has been deleted. 513 * @param force whether or not this user should be deleted even if they still own files. 514 */ 515 public void delete(boolean notifyUser, boolean force) { 516 String queryString = new QueryStringBuilder() 517 .appendParam("notify", String.valueOf(notifyUser)) 518 .appendParam("force", String.valueOf(force)) 519 .toString(); 520 521 URL url = USER_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID()); 522 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE"); 523 BoxAPIResponse response = request.send(); 524 response.disconnect(); 525 } 526 527 /** 528 * Updates the information about this user with any info fields that have been modified locally. 529 * 530 * <p>Note: This method is only available to enterprise admins.</p> 531 * 532 * @param info info the updated info. 533 */ 534 public void updateInfo(BoxUser.Info info) { 535 URL url = USER_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 536 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 537 request.setBody(info.getPendingChanges()); 538 BoxJSONResponse response = (BoxJSONResponse) request.send(); 539 JsonObject jsonObject = JsonObject.readFrom(response.getJSON()); 540 info.update(jsonObject); 541 } 542 543 /** 544 * @deprecated As of release 2.22.0, replaced by {@link #transferContent(String)} ()} 545 * 546 * 547 * Moves all of the owned content from within one user’s folder into a new folder in another user's account. 548 * You can move folders across users as long as the you have administrative permissions and the 'source' 549 * user owns the folders. Per the documentation at the link below, this will move everything from the root 550 * folder, as this is currently the only mode of operation supported. 551 * 552 * See also https://developer.box.com/en/reference/put-users-id-folders-id/ 553 * 554 * @param sourceUserID the user id of the user whose files will be the source for this operation 555 * @return info for the newly created folder 556 */ 557 @Deprecated 558 public BoxFolder.Info moveFolderToUser(String sourceUserID) { 559 // Currently the API only supports moving of the root folder (0), hence the hard coded "0" 560 URL url = MOVE_FOLDER_TO_USER_TEMPLATE.build(this.getAPI().getBaseURL(), sourceUserID, "0"); 561 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 562 JsonObject idValue = new JsonObject(); 563 idValue.add("id", this.getID()); 564 JsonObject ownedBy = new JsonObject(); 565 ownedBy.add("owned_by", idValue); 566 request.setBody(ownedBy.toString()); 567 BoxJSONResponse response = (BoxJSONResponse) request.send(); 568 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 569 BoxFolder movedFolder = new BoxFolder(this.getAPI(), responseJSON.get("id").asString()); 570 571 return movedFolder.new Info(responseJSON); 572 } 573 574 /** 575 * Moves all of the owned content from within one user’s folder into a new folder in another user's account. 576 * You can move folders across users as long as the you have administrative permissions and the 'source' 577 * user owns the folders. Per the documentation at the link below, this will move everything from the root 578 * folder, as this is currently the only mode of operation supported. 579 * 580 * See also https://developer.box.com/en/reference/put-users-id-folders-id/ 581 * 582 * @param destinationUserID the user id of the user that you wish to transfer content to. 583 * @return info for the newly created folder. 584 */ 585 public BoxFolder.Info transferContent(String destinationUserID) { 586 URL url = MOVE_FOLDER_TO_USER_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), "0"); 587 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 588 JsonObject destinationUser = new JsonObject(); 589 destinationUser.add("id", destinationUserID); 590 JsonObject ownedBy = new JsonObject(); 591 ownedBy.add("owned_by", destinationUser); 592 request.setBody(ownedBy.toString()); 593 BoxJSONResponse response = (BoxJSONResponse) request.send(); 594 JsonObject responseJSON = JsonObject.readFrom(response.getJSON()); 595 BoxFolder movedFolder = new BoxFolder(this.getAPI(), responseJSON.get("id").asString()); 596 597 return movedFolder.new Info(responseJSON); 598 } 599 600 601 /** 602 * Retrieves the avatar of a user as an InputStream. 603 * 604 * @return InputStream representing the user avater. 605 */ 606 public InputStream getAvatar() { 607 URL url = USER_AVATAR_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 608 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 609 BoxAPIResponse response = request.send(); 610 611 return response.getBody(); 612 } 613 614 /** 615 * Enumerates the possible roles that a user can have within an enterprise. 616 */ 617 public enum Role { 618 /** 619 * The user is an administrator of their enterprise. 620 */ 621 ADMIN ("admin"), 622 623 /** 624 * The user is a co-administrator of their enterprise. 625 */ 626 COADMIN ("coadmin"), 627 628 /** 629 * The user is a regular user within their enterprise. 630 */ 631 USER ("user"); 632 633 private final String jsonValue; 634 635 private Role(String jsonValue) { 636 this.jsonValue = jsonValue; 637 } 638 639 static Role fromJSONValue(String jsonValue) { 640 return Role.valueOf(jsonValue.toUpperCase()); 641 } 642 643 String toJSONValue() { 644 return this.jsonValue; 645 } 646 } 647 648 /** 649 * Enumerates the possible statuses that a user's account can have. 650 */ 651 public enum Status { 652 /** 653 * The user's account is active. 654 */ 655 ACTIVE ("active"), 656 657 /** 658 * The user's account is inactive. 659 */ 660 INACTIVE ("inactive"), 661 662 /** 663 * The user's account cannot delete or edit content. 664 */ 665 CANNOT_DELETE_EDIT ("cannot_delete_edit"), 666 667 /** 668 * The user's account cannot delete, edit, or upload content. 669 */ 670 CANNOT_DELETE_EDIT_UPLOAD ("cannot_delete_edit_upload"); 671 672 private final String jsonValue; 673 674 private Status(String jsonValue) { 675 this.jsonValue = jsonValue; 676 } 677 678 static Status fromJSONValue(String jsonValue) { 679 return Status.valueOf(jsonValue.toUpperCase()); 680 } 681 682 String toJSONValue() { 683 return this.jsonValue; 684 } 685 } 686 687 /** 688 * Contains information about a BoxUser. 689 */ 690 public class Info extends BoxCollaborator.Info { 691 private String login; 692 private Role role; 693 private String language; 694 private String timezone; 695 private long spaceAmount; 696 private long spaceUsed; 697 private long maxUploadSize; 698 private boolean canSeeManagedUsers; 699 private boolean isSyncEnabled; 700 private boolean isExternalCollabRestricted; 701 private Status status; 702 private String jobTitle; 703 private String phone; 704 private String address; 705 private String avatarURL; 706 private boolean isExemptFromDeviceLimits; 707 private boolean isExemptFromLoginVerification; 708 private boolean isPasswordResetRequired; 709 private boolean isPlatformAccessOnly; 710 private String externalAppUserId; 711 private BoxEnterprise enterprise; 712 private List<String> myTags; 713 private String hostname; 714 private Map<String, String> trackingCodes; 715 716 /** 717 * Constructs an empty Info object. 718 */ 719 public Info() { 720 super(); 721 } 722 723 /** 724 * Constructs an Info object by parsing information from a JSON string. 725 * @param json the JSON string to parse. 726 */ 727 public Info(String json) { 728 super(json); 729 } 730 731 Info(JsonObject jsonObject) { 732 super(jsonObject); 733 } 734 735 @Override 736 public BoxUser getResource() { 737 return BoxUser.this; 738 } 739 740 /** 741 * Gets the email address the user uses to login. 742 * @return the email address the user uses to login. 743 */ 744 public String getLogin() { 745 return this.login; 746 } 747 748 /** 749 * Sets the email address the user uses to login. The new login must be one of the user's already confirmed 750 * email aliases. 751 * @param login one of the user's confirmed email aliases. 752 */ 753 public void setLogin(String login) { 754 this.login = login; 755 this.addPendingChange("login", login); 756 } 757 758 /** 759 * Gets the user's enterprise role. 760 * @return the user's enterprise role. 761 */ 762 public Role getRole() { 763 return this.role; 764 } 765 766 /** 767 * Sets the user's role in their enterprise. 768 * @param role the user's new role in their enterprise. 769 */ 770 public void setRole(Role role) { 771 this.role = role; 772 this.addPendingChange("role", role.name().toLowerCase()); 773 } 774 775 /** 776 * Gets the language of the user. 777 * @return the language of the user. 778 */ 779 public String getLanguage() { 780 return this.language; 781 } 782 783 /** 784 * Sets the language of the user. 785 * @param language the new language of the user. 786 */ 787 public void setLanguage(String language) { 788 this.language = language; 789 this.addPendingChange("language", language); 790 } 791 792 /** 793 * Gets the timezone of the user. 794 * @return the timezone of the user. 795 */ 796 public String getTimezone() { 797 return this.timezone; 798 } 799 800 /** 801 * Sets the timezone of the user. 802 * @param timezone the new timezone of the user. 803 */ 804 public void setTimezone(String timezone) { 805 this.timezone = timezone; 806 this.addPendingChange("timezone", timezone); 807 } 808 809 /** 810 * Gets the user's total available space in bytes. 811 * @return the user's total available space in bytes. 812 */ 813 public long getSpaceAmount() { 814 return this.spaceAmount; 815 } 816 817 /** 818 * Sets the user's total available space in bytes. 819 * @param spaceAmount the new amount of space available to the user in bytes, or -1 for unlimited storage. 820 */ 821 public void setSpaceAmount(long spaceAmount) { 822 this.spaceAmount = spaceAmount; 823 this.addPendingChange("space_amount", spaceAmount); 824 } 825 826 /** 827 * Gets the amount of space the user has used in bytes. 828 * @return the amount of space the user has used in bytes. 829 */ 830 public long getSpaceUsed() { 831 return this.spaceUsed; 832 } 833 834 /** 835 * Gets the maximum individual file size in bytes the user can have. 836 * @return the maximum individual file size in bytes the user can have. 837 */ 838 public long getMaxUploadSize() { 839 return this.maxUploadSize; 840 } 841 842 /** 843 * Gets the user's current account status. 844 * @return the user's current account status. 845 */ 846 public Status getStatus() { 847 return this.status; 848 } 849 850 /** 851 * Sets the user's current account status. 852 * @param status the user's new account status. 853 */ 854 public void setStatus(Status status) { 855 this.status = status; 856 this.addPendingChange("status", status.name().toLowerCase()); 857 } 858 859 /** 860 * Gets the job title of the user. 861 * @return the job title of the user. 862 */ 863 public String getJobTitle() { 864 return this.jobTitle; 865 } 866 867 /** 868 * Sets the job title of the user. 869 * @param jobTitle the new job title of the user. 870 */ 871 public void setJobTitle(String jobTitle) { 872 this.jobTitle = jobTitle; 873 this.addPendingChange("job_title", jobTitle); 874 } 875 876 /** 877 * Gets the phone number of the user. 878 * @return the phone number of the user. 879 */ 880 public String getPhone() { 881 return this.phone; 882 } 883 884 /** 885 * Sets the phone number of the user. 886 * @param phone the new phone number of the user. 887 */ 888 public void setPhone(String phone) { 889 this.phone = phone; 890 this.addPendingChange("phone", phone); 891 } 892 893 /** 894 * Gets the address of the user. 895 * @return the address of the user. 896 */ 897 public String getAddress() { 898 return this.address; 899 } 900 901 /** 902 * Sets the address of the user. 903 * @param address the new address of the user. 904 */ 905 public void setAddress(String address) { 906 this.address = address; 907 this.addPendingChange("address", address); 908 } 909 910 /** 911 * Gets the URL of the user's avatar. 912 * @return the URL of the user's avatar. 913 */ 914 public String getAvatarURL() { 915 return this.avatarURL; 916 } 917 918 /** 919 * Gets the enterprise that the user belongs to. 920 * @return the enterprise that the user belongs to. 921 */ 922 public BoxEnterprise getEnterprise() { 923 return this.enterprise; 924 } 925 926 /** 927 * Removes the user from their enterprise and converts them to a standalone free user. 928 */ 929 public void removeEnterprise() { 930 this.removeChildObject("enterprise"); 931 this.enterprise = null; 932 this.addChildObject("enterprise", null); 933 } 934 935 /** 936 * Gets whether or not the user can use Box Sync. 937 * @return true if the user can use Box Sync; otherwise false. 938 */ 939 public boolean getIsSyncEnabled() { 940 return this.isSyncEnabled; 941 } 942 943 /** 944 * Sets whether this user is allowed or not to collaborate with users outside their enterprise. 945 * @param isExternalCollabRestricted whether the user is allowed to collaborate outside their enterprise. 946 */ 947 public void setIsExternalCollabRestricted(boolean isExternalCollabRestricted) { 948 this.isExternalCollabRestricted = isExternalCollabRestricted; 949 this.addPendingChange("is_external_collab_restricted", isExternalCollabRestricted); 950 } 951 952 /** 953 * Gets whether this user is allowed or not to collaborate with users outside their enterprise. 954 * @return true if this user is not allowed to collaborate with users outside their enterprise; otherwise false. 955 */ 956 public boolean getIsExternalCollabRestricted() { 957 return this.isExternalCollabRestricted; 958 } 959 960 /** 961 * Sets whether or not the user can use Box Sync. 962 * @param enabled whether or not the user can use Box Sync. 963 */ 964 public void setIsSyncEnabled(boolean enabled) { 965 this.isSyncEnabled = enabled; 966 this.addPendingChange("is_sync_enabled", enabled); 967 } 968 969 /** 970 * Gets whether or not the user can see other enterprise users in their contact list. 971 * @return true if the user can see other enterprise users in their contact list; otherwise false. 972 */ 973 public boolean getCanSeeManagedUsers() { 974 return this.canSeeManagedUsers; 975 } 976 977 /** 978 * Sets whether or not the user can see other enterprise users in their contact list. 979 * @param canSeeManagedUsers whether or not the user can see other enterprise users in their contact list. 980 */ 981 public void setCanSeeManagedUsers(boolean canSeeManagedUsers) { 982 this.canSeeManagedUsers = canSeeManagedUsers; 983 this.addPendingChange("can_see_managed_users", canSeeManagedUsers); 984 } 985 986 /** 987 * Gets whether or not the user is exempt from enterprise device limits. 988 * @return true if the user is exempt from enterprise device limits; otherwise false. 989 */ 990 public boolean getIsExemptFromDeviceLimits() { 991 return this.isExemptFromDeviceLimits; 992 } 993 994 /** 995 * Sets whether or not the user is exempt from enterprise device limits. 996 * @param isExemptFromDeviceLimits whether or not the user is exempt from enterprise device limits. 997 */ 998 public void setIsExemptFromDeviceLimits(boolean isExemptFromDeviceLimits) { 999 this.isExemptFromDeviceLimits = isExemptFromDeviceLimits; 1000 this.addPendingChange("is_exempt_from_device_limits", isExemptFromDeviceLimits); 1001 } 1002 1003 /** 1004 * Gets whether or not the user must use two-factor authentication. 1005 * @return true if the user must use two-factor authentication; otherwise false. 1006 */ 1007 public boolean getIsExemptFromLoginVerification() { 1008 return this.isExemptFromLoginVerification; 1009 } 1010 1011 /** 1012 * Sets whether or not the user must use two-factor authentication. 1013 * @param isExemptFromLoginVerification whether or not the user must use two-factor authentication. 1014 */ 1015 public void setIsExemptFromLoginVerification(boolean isExemptFromLoginVerification) { 1016 this.isExemptFromLoginVerification = isExemptFromLoginVerification; 1017 this.addPendingChange("is_exempt_from_login_verification", isExemptFromLoginVerification); 1018 } 1019 1020 /** 1021 * Gets whether or not the user is required to reset password. 1022 * @return true if the user is required to reset password; otherwise false. 1023 */ 1024 public boolean getIsPasswordResetRequired() { 1025 return this.isPasswordResetRequired; 1026 } 1027 1028 /** 1029 * Sets whether or not the user is required to reset password. 1030 * @param isPasswordResetRequired whether or not the user is required to reset password. 1031 */ 1032 public void setIsPasswordResetRequired(boolean isPasswordResetRequired) { 1033 this.isPasswordResetRequired = isPasswordResetRequired; 1034 this.addPendingChange("is_password_reset_required", isPasswordResetRequired); 1035 } 1036 1037 /** 1038 * Gets whether or not the user we are creating is an app user with Box Developer Edition. 1039 * @return true if the new user is an app user for Box Developer Addition; otherwise false. 1040 */ 1041 public boolean getIsPlatformAccessOnly() { 1042 return this.isPlatformAccessOnly; 1043 } 1044 1045 /** 1046 * Gets the external app user id that has been set for the app user. 1047 * @return the external app user id. 1048 */ 1049 public String getExternalAppUserId() { 1050 return this.externalAppUserId; 1051 } 1052 1053 /** 1054 * Sets the external app user id. 1055 * @param externalAppUserId external app user id. 1056 */ 1057 public void setExternalAppUserId(String externalAppUserId) { 1058 this.externalAppUserId = externalAppUserId; 1059 this.addPendingChange("external_app_user_id", externalAppUserId); 1060 } 1061 1062 /** 1063 * Gets the tags for all files and folders owned by this user. 1064 * @return the tags for all files and folders owned by this user. 1065 */ 1066 public List<String> getMyTags() { 1067 return this.myTags; 1068 } 1069 1070 /** 1071 * Gets the root (protocol, subdomain, domain) of any links that need to be generated for this user. 1072 * @return the root (protocol, subdomain, domain) of any links that need to be generated for this user. 1073 */ 1074 public String getHostname() { 1075 return this.hostname; 1076 } 1077 1078 /** 1079 * Gets the tracking defined for each entity. 1080 * @return a Map with tracking codes. 1081 */ 1082 public Map<String, String> getTrackingCodes() { 1083 return this.trackingCodes; 1084 } 1085 1086 /** 1087 * Allows admin to set attributes specific for a group of users. 1088 * @param trackingCodes a Map representing the user's new tracking codes 1089 */ 1090 public void setTrackingCodes(Map<String, String> trackingCodes) { 1091 this.trackingCodes = trackingCodes; 1092 this.addPendingChange("tracking_codes", this.trackingCodesJson()); 1093 } 1094 1095 /** 1096 * Allows the admin to append new tracking codes to the previous existing list. 1097 * @param name the name or `key` of the attribute to set. 1098 * @param value the value of the attribute to set. 1099 */ 1100 public void appendTrackingCodes(String name, String value) { 1101 this.getTrackingCodes().put(name, value); 1102 this.addPendingChange("tracking_codes", this.trackingCodesJson()); 1103 } 1104 1105 private JsonArray trackingCodesJson() { 1106 JsonArray trackingCodesJsonArray = new JsonArray(); 1107 for (String attrKey : this.trackingCodes.keySet()) { 1108 JsonObject trackingCode = new JsonObject(); 1109 trackingCode.set("type", "tracking_code"); 1110 trackingCode.set("name", attrKey); 1111 trackingCode.set("value", this.trackingCodes.get(attrKey)); 1112 trackingCodesJsonArray.add(trackingCode); 1113 } 1114 return trackingCodesJsonArray; 1115 } 1116 1117 @Override 1118 protected void parseJSONMember(JsonObject.Member member) { 1119 super.parseJSONMember(member); 1120 1121 JsonValue value = member.getValue(); 1122 String memberName = member.getName(); 1123 try { 1124 if (memberName.equals("login")) { 1125 this.login = value.asString(); 1126 } else if (memberName.equals("role")) { 1127 this.role = Role.fromJSONValue(value.asString()); 1128 } else if (memberName.equals("language")) { 1129 this.language = value.asString(); 1130 } else if (memberName.equals("timezone")) { 1131 this.timezone = value.asString(); 1132 } else if (memberName.equals("space_amount")) { 1133 this.spaceAmount = Double.valueOf(value.toString()).longValue(); 1134 } else if (memberName.equals("space_used")) { 1135 this.spaceUsed = Double.valueOf(value.toString()).longValue(); 1136 } else if (memberName.equals("max_upload_size")) { 1137 this.maxUploadSize = Double.valueOf(value.toString()).longValue(); 1138 } else if (memberName.equals("status")) { 1139 this.status = Status.fromJSONValue(value.asString()); 1140 } else if (memberName.equals("job_title")) { 1141 this.jobTitle = value.asString(); 1142 } else if (memberName.equals("phone")) { 1143 this.phone = value.asString(); 1144 } else if (memberName.equals("address")) { 1145 this.address = value.asString(); 1146 } else if (memberName.equals("avatar_url")) { 1147 this.avatarURL = value.asString(); 1148 } else if (memberName.equals("can_see_managed_users")) { 1149 this.canSeeManagedUsers = value.asBoolean(); 1150 } else if (memberName.equals("is_sync_enabled")) { 1151 this.isSyncEnabled = value.asBoolean(); 1152 } else if (memberName.equals("is_external_collab_restricted")) { 1153 this.isExternalCollabRestricted = value.asBoolean(); 1154 } else if (memberName.equals("is_exempt_from_device_limits")) { 1155 this.isExemptFromDeviceLimits = value.asBoolean(); 1156 } else if (memberName.equals("is_exempt_from_login_verification")) { 1157 this.isExemptFromLoginVerification = value.asBoolean(); 1158 } else if (memberName.equals("is_password_reset_required")) { 1159 this.isPasswordResetRequired = value.asBoolean(); 1160 } else if (memberName.equals("is_platform_access_only")) { 1161 this.isPlatformAccessOnly = value.asBoolean(); 1162 } else if (memberName.equals("external_app_user_id")) { 1163 this.externalAppUserId = value.asString(); 1164 } else if (memberName.equals("enterprise")) { 1165 JsonObject jsonObject = value.asObject(); 1166 if (this.enterprise == null) { 1167 this.enterprise = new BoxEnterprise(jsonObject); 1168 } else { 1169 this.enterprise.update(jsonObject); 1170 } 1171 } else if (memberName.equals("my_tags")) { 1172 this.myTags = this.parseMyTags(value.asArray()); 1173 } else if (memberName.equals("hostname")) { 1174 this.hostname = value.asString(); 1175 } else if (memberName.equals("tracking_codes")) { 1176 this.trackingCodes = this.parseTrackingCodes(value.asArray()); 1177 } 1178 } catch (Exception e) { 1179 throw new BoxDeserializationException(memberName, value.toString(), e); 1180 } 1181 1182 } 1183 1184 private List<String> parseMyTags(JsonArray jsonArray) { 1185 List<String> myTags = new ArrayList<String>(jsonArray.size()); 1186 for (JsonValue value : jsonArray) { 1187 myTags.add(value.asString()); 1188 } 1189 1190 return myTags; 1191 } 1192 private Map<String, String> parseTrackingCodes(JsonArray jsonArray) { 1193 Map<String, String> result = new HashMap<String, String>(); 1194 if (jsonArray == null) { 1195 return null; 1196 } 1197 List<JsonValue> valuesList = jsonArray.values(); 1198 for (JsonValue jsonValue : valuesList) { 1199 JsonObject object = jsonValue.asObject(); 1200 result.put(object.get("name").asString().toString(), object.get("value").asString().toString()); 1201 } 1202 return result; 1203 } 1204 } 1205}