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