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