• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

box / box-java-sdk / #4583

29 Apr 2025 07:23AM UTC coverage: 72.058% (-0.002%) from 72.06%
#4583

push

github

web-flow
fix: use `Locale.ROOT` to prevent issues with non-US locales (#1306)

14 of 23 new or added lines in 16 files covered. (60.87%)

1 existing line in 1 file now uncovered.

8216 of 11402 relevant lines covered (72.06%)

0.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.24
/src/main/java/com/box/sdk/BoxUser.java
1
package com.box.sdk;
2

3
import static com.box.sdk.BinaryBodyUtils.writeStream;
4
import static com.box.sdk.http.HttpMethod.DELETE;
5
import static com.box.sdk.internal.utils.JsonUtils.addIfNotNull;
6

7
import com.eclipsesource.json.Json;
8
import com.eclipsesource.json.JsonArray;
9
import com.eclipsesource.json.JsonObject;
10
import com.eclipsesource.json.JsonValue;
11
import java.io.ByteArrayInputStream;
12
import java.io.ByteArrayOutputStream;
13
import java.io.File;
14
import java.io.FileInputStream;
15
import java.io.FileNotFoundException;
16
import java.io.IOException;
17
import java.io.InputStream;
18
import java.io.OutputStream;
19
import java.net.URL;
20
import java.util.ArrayList;
21
import java.util.Collection;
22
import java.util.HashMap;
23
import java.util.List;
24
import java.util.Map;
25
import java.util.Optional;
26

27
/**
28
 * Represents a Box user account.
29
 *
30
 * <p>Unless otherwise noted, the methods in this class can throw an unchecked {@link BoxAPIException} (unchecked
31
 * meaning that the compiler won't force you to handle it) if an error occurs. If you wish to implement custom error
32
 * handling for errors related to the Box REST API, you should capture this exception explicitly.</p>
33
 */
34
@BoxResourceType("user")
35
public class BoxUser extends BoxCollaborator {
36

37
    /**
38
     * An array of all possible file fields that can be requested when calling {@link #getInfo(String...)}.
39
     */
40
    public static final String[] ALL_FIELDS = {"type", "id", "name", "login", "created_at", "modified_at", "role",
1✔
41
        "language", "timezone", "space_amount", "space_used", "max_upload_size", "tracking_codes",
42
        "can_see_managed_users", "is_sync_enabled", "is_external_collab_restricted", "status", "job_title", "phone",
43
        "address", "avatar_url", "is_exempt_from_device_limits", "is_exempt_from_login_verification", "enterprise",
44
        "my_tags", "hostname", "is_platform_access_only", "external_app_user_id", "notification_email"};
45

46
    /**
47
     * User URL Template.
48
     */
49
    public static final URLTemplate USER_URL_TEMPLATE = new URLTemplate("users/%s");
1✔
50
    /**
51
     * Get Me URL Template.
52
     */
53
    public static final URLTemplate GET_ME_URL = new URLTemplate("users/me");
1✔
54
    /**
55
     * Users URL Template.
56
     */
57
    public static final URLTemplate USERS_URL_TEMPLATE = new URLTemplate("users");
1✔
58
    /**
59
     * User Memberships URL Template.
60
     */
61
    public static final URLTemplate USER_MEMBERSHIPS_URL_TEMPLATE = new URLTemplate("users/%s/memberships");
1✔
62
    /**
63
     * E-Mail Alias URL Template.
64
     */
65
    public static final URLTemplate EMAIL_ALIAS_URL_TEMPLATE = new URLTemplate("users/%s/email_aliases/%s");
1✔
66
    /**
67
     * E-Mail Aliases URL Template.
68
     */
69
    public static final URLTemplate EMAIL_ALIASES_URL_TEMPLATE = new URLTemplate("users/%s/email_aliases");
1✔
70
    /**
71
     * Move Folder To User Template.
72
     */
73
    public static final URLTemplate MOVE_FOLDER_TO_USER_TEMPLATE = new URLTemplate("users/%s/folders/%s");
1✔
74
    /**
75
     * User Avatar Template.
76
     */
77
    public static final URLTemplate USER_AVATAR_TEMPLATE = new URLTemplate("users/%s/avatar");
1✔
78

79
    /**
80
     * Constructs a BoxUser for a user with a given ID.
81
     *
82
     * @param api the API connection to be used by the user.
83
     * @param id  the ID of the user.
84
     */
85
    public BoxUser(BoxAPIConnection api, String id) {
86
        super(api, id);
1✔
87
    }
1✔
88

89
    /**
90
     * Provisions a new app user in an enterprise using Box Developer Edition.
91
     *
92
     * @param api  the API connection to be used by the created user.
93
     * @param name the name of the user.
94
     * @param fields the fields to retrieve. Leave this out for the standard fields.
95
     * @return the created user's info.
96
     */
97
    public static BoxUser.Info createAppUser(BoxAPIConnection api, String name, String... fields) {
98
        return createAppUser(api, name, new CreateUserParams(), fields);
1✔
99
    }
100

101
    /**
102
     * Provisions a new app user in an enterprise with additional user information using Box Developer Edition.
103
     *
104
     * @param api    the API connection to be used by the created user.
105
     * @param name   the name of the user.
106
     * @param params additional user information.
107
     * @param fields the fields to retrieve. Leave this out for the standard fields.
108
     * @return the created user's info.
109
     */
110
    public static BoxUser.Info createAppUser(BoxAPIConnection api, String name,
111
                                             CreateUserParams params, String... fields) {
112

113
        params.setIsPlatformAccessOnly(true);
1✔
114
        return createEnterpriseUser(api, null, name, params, fields);
1✔
115
    }
116

117
    /**
118
     * Provisions a new user in an enterprise.
119
     *
120
     * @param api   the API connection to be used by the created user.
121
     * @param login the email address the user will use to login.
122
     * @param name  the name of the user.
123
     * @param fields the fields to retrieve. Leave this out for the standard fields.
124
     * @return the created user's info.
125
     */
126
    public static BoxUser.Info createEnterpriseUser(BoxAPIConnection api, String login, String name, String... fields) {
127
        return createEnterpriseUser(api, login, name, null, fields);
1✔
128
    }
129

130
    /**
131
     * Provisions a new user in an enterprise with additional user information.
132
     *
133
     * @param api    the API connection to be used by the created user.
134
     * @param login  the email address the user will use to login.
135
     * @param name   the name of the user.
136
     * @param params additional user information.
137
     * @param fields the fields to retrieve. Leave this out for the standard fields.
138
     * @return the created user's info.
139
     */
140
    public static BoxUser.Info createEnterpriseUser(BoxAPIConnection api, String login, String name,
141
                                                    CreateUserParams params, String... fields) {
142

143
        JsonObject requestJSON = new JsonObject();
1✔
144
        requestJSON.add("login", login);
1✔
145
        requestJSON.add("name", name);
1✔
146

147
        if (params != null) {
1✔
148
            if (params.getRole() != null) {
1✔
149
                requestJSON.add("role", params.getRole().toJSONValue());
×
150
            }
151

152
            if (params.getStatus() != null) {
1✔
153
                requestJSON.add("status", params.getStatus().toJSONValue());
×
154
            }
155

156
            if (params.getTrackingCodes() != null) {
1✔
157
                requestJSON.add("tracking_codes", toTrackingCodesJson(params.getTrackingCodes()));
×
158
            }
159

160
            addIfNotNull(requestJSON, "language", params.getLanguage());
1✔
161
            addIfNotNull(requestJSON, "is_sync_enabled", params.getIsSyncEnabled());
1✔
162
            addIfNotNull(requestJSON, "job_title", params.getJobTitle());
1✔
163
            addIfNotNull(requestJSON, "phone", params.getPhone());
1✔
164
            addIfNotNull(requestJSON, "address", params.getAddress());
1✔
165
            addIfNotNull(requestJSON, "space_amount", params.getSpaceAmount());
1✔
166
            addIfNotNull(requestJSON, "can_see_managed_users", params.getCanSeeManagedUsers());
1✔
167
            addIfNotNull(requestJSON, "timezone", params.getTimezone());
1✔
168
            addIfNotNull(requestJSON, "is_exempt_from_device_limits", params.getIsExemptFromDeviceLimits());
1✔
169
            addIfNotNull(requestJSON, "is_exempt_from_login_verification", params.getIsExemptFromLoginVerification());
1✔
170
            addIfNotNull(requestJSON, "is_platform_access_only", params.getIsPlatformAccessOnly());
1✔
171
            addIfNotNull(requestJSON, "external_app_user_id", params.getExternalAppUserId());
1✔
172
            addIfNotNull(requestJSON, "is_external_collab_restricted", params.getIsExternalCollabRestricted());
1✔
173
        }
174

175
        QueryStringBuilder queryString = new QueryStringBuilder();
1✔
176
        if (fields.length > 0) {
1✔
177
            queryString.appendParam("fields", fields);
1✔
178
        }
179
        URL url = USERS_URL_TEMPLATE.buildWithQuery(api.getBaseURL(), queryString.toString());
1✔
180
        BoxJSONRequest request = new BoxJSONRequest(api, url, "POST");
1✔
181
        request.setBody(requestJSON.toString());
1✔
182
        try (BoxJSONResponse response = request.send()) {
1✔
183
            JsonObject responseJSON = Json.parse(response.getJSON()).asObject();
1✔
184

185
            BoxUser createdUser = new BoxUser(api, responseJSON.get("id").asString());
1✔
186
            return createdUser.new Info(responseJSON);
1✔
187
        }
188
    }
189

190
    /**
191
     * Gets the current user.
192
     *
193
     * @param api the API connection of the current user.
194
     * @return the current user.
195
     */
196
    public static BoxUser getCurrentUser(BoxAPIConnection api) {
197
        URL url = GET_ME_URL.build(api.getBaseURL());
1✔
198
        BoxJSONRequest request = new BoxJSONRequest(api, url, "GET");
1✔
199
        try (BoxJSONResponse response = request.send()) {
1✔
200
            JsonObject jsonObject = Json.parse(response.getJSON()).asObject();
1✔
201
            return new BoxUser(api, jsonObject.get("id").asString());
1✔
202
        }
203
    }
204

205
    /**
206
     * Returns an iterable containing all the enterprise users.
207
     *
208
     * @param api the API connection to be used when retrieving the users.
209
     * @return an iterable containing all the enterprise users.
210
     */
211
    public static Iterable<BoxUser.Info> getAllEnterpriseUsers(final BoxAPIConnection api) {
212
        return getAllEnterpriseUsers(api, false, null);
1✔
213
    }
214

215

216
    /**
217
     * Returns an iterable containing all the enterprise users. Uses marker based pagination.
218
     *
219
     * @param api       the API connection to be used when retrieving the users.
220
     * @param usemarker Boolean that determines whether to use marker based pagination.
221
     * @param marker    The marker at which the iterator will begin.
222
     * @return an iterable containing all the enterprise users.
223
     */
224
    public static Iterable<BoxUser.Info> getAllEnterpriseUsers(final BoxAPIConnection api, final boolean usemarker,
225
                                                               final String marker) {
226
        return getUsersInfoForType(api, null, null, null, usemarker, marker);
1✔
227
    }
228

229
    /**
230
     * Returns an iterable containing all the enterprise users that matches the filter and specifies which child fields
231
     * to retrieve from the API.
232
     *
233
     * @param api        the API connection to be used when retrieving the users.
234
     * @param filterTerm used to filter the results to only users starting with this string in either the name or the
235
     *                   login. Can be null to not filter the results.
236
     * @param fields     the fields to retrieve. Leave this out for the standard fields.
237
     * @return an iterable containing all the enterprise users that matches the filter.
238
     */
239
    public static Iterable<BoxUser.Info> getAllEnterpriseUsers(final BoxAPIConnection api, final String filterTerm,
240
                                                               final String... fields) {
241
        return getUsersInfoForType(api, filterTerm, null, null, false, null, fields);
×
242
    }
243

244
    /**
245
     * Returns an iterable containing all the enterprise users that matches the filter and specifies which child fields
246
     * to retrieve from the API. Uses marker based pagination.
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 starting with this string in either the name or the
250
     *                   login. Can be null to not filter the results.
251
     * @param usemarker  Boolean that determines whether to use marker based pagination.
252
     * @param marker     The marker at which the iterator will begin.
253
     * @param fields     the fields to retrieve. Leave this out for the standard fields.
254
     * @return an iterable containing all the enterprise users that matches the filter.
255
     */
256
    public static Iterable<BoxUser.Info> getAllEnterpriseUsers(
257
        final BoxAPIConnection api,
258
        final String filterTerm,
259
        final boolean usemarker,
260
        final String marker,
261
        final String... fields
262
    ) {
263
        return getUsersInfoForType(api, filterTerm, null, null, usemarker, marker, fields);
×
264
    }
265

266
    /**
267
     * Gets a limited set of information about an external user. (A user collaborating
268
     * on content owned by the enterprise). Note: Only fields the user has permission to
269
     * see will be returned with values. Other fields will return a value of null.
270
     *
271
     * @param api        the API connection to be used when retrieving the users.
272
     * @param filterTerm used to filter the results to only users matching the given login.
273
     *                   This does exact match only, so if no filter term is passed in, nothing
274
     *                   will be returned.
275
     * @param fields     the fields to retrieve. Leave this out for the standard fields.
276
     * @return an iterable containing external users matching the given email
277
     */
278
    public static Iterable<BoxUser.Info> getExternalUsers(final BoxAPIConnection api, final String filterTerm,
279
                                                          final String... fields) {
280
        return getUsersInfoForType(api, filterTerm, "external", null, false, null, fields);
×
281
    }
282

283
    /**
284
     * Gets a limited set of information about an external user. (A user collaborating
285
     * on content owned by the enterprise). Note: Only fields the user has permission to
286
     * see will be returned with values. Other fields will return a value of null. Uses marker based pagination.
287
     *
288
     * @param api        the API connection to be used when retrieving the users.
289
     * @param filterTerm used to filter the results to only users matching the given login.
290
     *                   This does exact match only, so if no filter term is passed in, nothing
291
     *                   will be returned.
292
     * @param usemarker  Boolean that determines whether to use marker based pagination.
293
     * @param marker     The marker at which the iterator will begin.
294
     * @param fields     the fields to retrieve. Leave this out for the standard fields.
295
     * @return an iterable containing external users matching the given email
296
     */
297
    public static Iterable<BoxUser.Info> getExternalUsers(
298
        final BoxAPIConnection api,
299
        final String filterTerm,
300
        final boolean usemarker,
301
        final String marker,
302
        final String... fields
303
    ) {
304
        return getUsersInfoForType(api, filterTerm, "external", null, usemarker, marker, fields);
×
305
    }
306

307
    /**
308
     * Gets any managed users that match the filter term as well as any external users that
309
     * match the filter term. For managed users it matches any users names or emails that
310
     * start with the term. For external, it only does full match on email. This method
311
     * is ideal to use in the case where you have a full email for a user and you don't
312
     * know if they're managed or external.
313
     *
314
     * @param api        the API connection to be used when retrieving the users.
315
     * @param filterTerm The filter term to lookup users by (login for external, login or name for managed)
316
     * @param fields     the fields to retrieve. Leave this out for the standard fields.
317
     * @return an iterable containing users matching the given email
318
     */
319
    public static Iterable<BoxUser.Info> getAllEnterpriseOrExternalUsers(
320
        final BoxAPIConnection api,
321
        final String filterTerm,
322
        final String... fields
323
    ) {
324
        return getUsersInfoForType(api, filterTerm, "all", null, false, null, fields);
×
325
    }
326

327
    /**
328
     * Gets any managed users that match the filter term as well as any external users that
329
     * match the filter term. For managed users it matches any users names or emails that
330
     * start with the term. For external, it only does full match on email. This method
331
     * is ideal to use in the case where you have a full email for a user and you don't
332
     * know if they're managed or external. Uses marker based pagination.
333
     *
334
     * @param api        the API connection to be used when retrieving the users.
335
     * @param filterTerm The filter term to lookup users by (login for external, login or name for managed)
336
     * @param usemarker  Boolean that determines whether to use marker based pagination.
337
     * @param marker     The marker at which the iterator will begin.
338
     * @param fields     the fields to retrieve. Leave this out for the standard fields.
339
     * @return an iterable containing users matching the given email
340
     */
341
    public static Iterable<BoxUser.Info> getAllEnterpriseOrExternalUsers(
342
        final BoxAPIConnection api,
343
        final String filterTerm,
344
        final boolean usemarker,
345
        final String marker,
346
        final String... fields
347
    ) {
348
        return getUsersInfoForType(api, filterTerm, "all", null, usemarker, marker, fields);
×
349
    }
350

351
    /**
352
     * Gets any app users that has an exact match with the externalAppUserId term.
353
     *
354
     * @param api               the API connection to be used when retrieving the users.
355
     * @param externalAppUserId the external app user id that has been set for app user
356
     * @param fields            the fields to retrieve. Leave this out for the standard fields.
357
     * @return an iterable containing users matching the given email
358
     */
359
    public static Iterable<BoxUser.Info> getAppUsersByExternalAppUserID(
360
        final BoxAPIConnection api,
361
        final String externalAppUserId,
362
        final String... fields
363
    ) {
364
        return getUsersInfoForType(api, null, null, externalAppUserId, false, null, fields);
×
365
    }
366

367
    /**
368
     * Gets any app users that has an exact match with the externalAppUserId term using marker based pagination.
369
     *
370
     * @param api               the API connection to be used when retrieving the users.
371
     * @param externalAppUserId the external app user id that has been set for 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 iterable containing users matching the given email
376
     */
377
    public static Iterable<BoxUser.Info> getAppUsersByExternalAppUserID(
378
        final BoxAPIConnection api,
379
        final String externalAppUserId,
380
        final boolean usemarker,
381
        String marker,
382
        final String... fields
383
    ) {
384
        return getUsersInfoForType(api, null, null, externalAppUserId, usemarker, marker, fields);
×
385
    }
386

387
    /**
388
     * Helper method to abstract out the common logic from the various users methods.
389
     *
390
     * @param api               the API connection to be used when retrieving the users.
391
     * @param filterTerm        The filter term to lookup users by (login for external, login or name for managed)
392
     * @param userType          The type of users we want to search with this request.
393
     *                          Valid values are 'managed' (enterprise users), 'external' or 'all'
394
     * @param externalAppUserId the external app user id that has been set for an app user
395
     * @param usemarker         Boolean that determines whether to use marker based pagination.
396
     * @param marker            The marker at which the iterator will begin.
397
     * @param fields            the fields to retrieve. Leave this out for the standard fields.
398
     * @return An iterator over the selected users.
399
     */
400
    private static Iterable<BoxUser.Info> getUsersInfoForType(
401
        final BoxAPIConnection api,
402
        final String filterTerm,
403
        final String userType,
404
        final String externalAppUserId,
405
        final boolean usemarker,
406
        final String marker,
407
        final String... fields
408
    ) {
409

410
        final QueryStringBuilder builder = new QueryStringBuilder();
1✔
411
        if (filterTerm != null) {
1✔
412
            builder.appendParam("filter_term", filterTerm);
×
413
        }
414
        if (userType != null) {
1✔
415
            builder.appendParam("user_type", userType);
×
416
        }
417
        if (externalAppUserId != null) {
1✔
418
            builder.appendParam("external_app_user_id", externalAppUserId);
×
419
        }
420
        if (usemarker) {
1✔
421
            builder.appendParam("usemarker", "true");
1✔
422
        }
423
        if (fields.length > 0) {
1✔
424
            builder.appendParam("fields", fields);
×
425
        }
426
        final URL url = USERS_URL_TEMPLATE.buildWithQuery(api.getBaseURL(), builder.toString());
1✔
427

428
        if (usemarker) {
1✔
429
            return new BoxResourceIterable<BoxUser.Info>(api, url, 100, null, marker) {
1✔
430
                @Override
431
                protected BoxUser.Info factory(JsonObject jsonObject) {
432
                    BoxUser user = new BoxUser(api, jsonObject.get("id").asString());
1✔
433
                    return user.new Info(jsonObject);
1✔
434
                }
435
            };
436
        } else {
437
            return () -> new BoxUserIterator(api, url);
1✔
438
        }
439
    }
440

441
    private static JsonArray toTrackingCodesJson(Map<String, String> trackingCodes) {
442
        JsonArray trackingCodesJsonArray = new JsonArray();
1✔
443
        for (String attrKey : trackingCodes.keySet()) {
1✔
444
            JsonObject trackingCode = new JsonObject();
1✔
445
            trackingCode.set("type", "tracking_code");
1✔
446
            trackingCode.set("name", attrKey);
1✔
447
            trackingCode.set("value", trackingCodes.get(attrKey));
1✔
448
            trackingCodesJsonArray.add(trackingCode);
1✔
449
        }
1✔
450
        return trackingCodesJsonArray;
1✔
451
    }
452

453
    /**
454
     * Gets information about this user.
455
     *
456
     * @param fields the optional fields to retrieve.
457
     * @return info about this user.
458
     */
459
    public BoxUser.Info getInfo(String... fields) {
460
        URL url;
461
        if (fields.length > 0) {
1✔
462
            String queryString = new QueryStringBuilder().appendParam("fields", fields).toString();
1✔
463
            url = USER_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID());
1✔
464
        } else {
1✔
465
            url = USER_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
1✔
466
        }
467
        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "GET");
1✔
468
        try (BoxJSONResponse response = request.send()) {
1✔
469
            JsonObject jsonObject = Json.parse(response.getJSON()).asObject();
1✔
470
            return new Info(jsonObject);
1✔
471
        }
472
    }
473

474
    /**
475
     * Gets information about all of the group memberships for this user.
476
     * Does not support paging.
477
     *
478
     * <p>Note: This method is only available to enterprise admins.</p>
479
     *
480
     * @return a collection of information about the group memberships for this user.
481
     */
482
    public Collection<BoxGroupMembership.Info> getMemberships() {
483
        BoxAPIConnection api = this.getAPI();
×
484
        URL url = USER_MEMBERSHIPS_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
×
485

486
        BoxJSONRequest request = new BoxJSONRequest(api, url, "GET");
×
487
        try (BoxJSONResponse response = request.send()) {
×
488
            JsonObject responseJSON = Json.parse(response.getJSON()).asObject();
×
489

490
            int entriesCount = responseJSON.get("total_count").asInt();
×
491
            Collection<BoxGroupMembership.Info> memberships = new ArrayList<>(entriesCount);
×
492
            JsonArray entries = responseJSON.get("entries").asArray();
×
493
            for (JsonValue entry : entries) {
×
494
                JsonObject entryObject = entry.asObject();
×
495
                BoxGroupMembership membership = new BoxGroupMembership(api, entryObject.get("id").asString());
×
496
                BoxGroupMembership.Info info = membership.new Info(entryObject);
×
497
                memberships.add(info);
×
498
            }
×
499

500
            return memberships;
×
501
        }
502
    }
503

504
    /**
505
     * Gets information about all of the group memberships for this user as iterable with paging support.
506
     *
507
     * @param fields the fields to retrieve.
508
     * @return an iterable with information about the group memberships for this user.
509
     */
510
    public Iterable<BoxGroupMembership.Info> getAllMemberships(String... fields) {
511
        final QueryStringBuilder builder = new QueryStringBuilder();
1✔
512
        if (fields.length > 0) {
1✔
513
            builder.appendParam("fields", fields);
×
514
        }
515
        return () -> {
1✔
516
            URL url = USER_MEMBERSHIPS_URL_TEMPLATE.buildWithQuery(
1✔
517
                BoxUser.this.getAPI().getBaseURL(), builder.toString(), BoxUser.this.getID());
1✔
518
            return new BoxGroupMembershipIterator(BoxUser.this.getAPI(), url);
1✔
519
        };
520
    }
521

522
    /**
523
     * Adds a new email alias to this user's account.
524
     *
525
     * @param email the email address to add as an alias.
526
     * @return the newly created email alias.
527
     */
528
    public EmailAlias addEmailAlias(String email) {
529
        return this.addEmailAlias(email, false);
1✔
530
    }
531

532
    /**
533
     * Adds a new email alias to this user's account and confirms it without user interaction.
534
     * This functionality is only available for enterprise admins.
535
     *
536
     * @param email       the email address to add as an alias.
537
     * @param isConfirmed whether or not the email alias should be automatically confirmed.
538
     * @return the newly created email alias.
539
     */
540
    public EmailAlias addEmailAlias(String email, boolean isConfirmed) {
541
        URL url = EMAIL_ALIASES_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
1✔
542
        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST");
1✔
543

544
        JsonObject requestJSON = new JsonObject()
1✔
545
            .add("email", email);
1✔
546

547
        if (isConfirmed) {
1✔
548
            requestJSON.add("is_confirmed", isConfirmed);
×
549
        }
550

551
        request.setBody(requestJSON.toString());
1✔
552
        try (BoxJSONResponse response = request.send()) {
1✔
553
            JsonObject responseJSON = Json.parse(response.getJSON()).asObject();
1✔
554
            return new EmailAlias(responseJSON);
1✔
555
        }
556
    }
557

558
    /**
559
     * Deletes an email alias from this user's account.
560
     *
561
     * <p>The IDs of the user's email aliases can be found by calling {@link #getEmailAliases}.</p>
562
     *
563
     * @param emailAliasID the ID of the email alias to delete.
564
     */
565
    public void deleteEmailAlias(String emailAliasID) {
566
        URL url = EMAIL_ALIAS_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), emailAliasID);
1✔
567
        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE");
1✔
568
        request.send().close();
1✔
569
    }
1✔
570

571
    /**
572
     * Gets a collection of all the email aliases for this user.
573
     *
574
     * <p>Note that the user's primary login email is not included in the collection of email aliases.</p>
575
     *
576
     * @return a collection of all the email aliases for this user.
577
     */
578
    public Collection<EmailAlias> getEmailAliases() {
579
        URL url = EMAIL_ALIASES_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
1✔
580
        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "GET");
1✔
581
        try (BoxJSONResponse response = request.send()) {
1✔
582
            JsonObject responseJSON = Json.parse(response.getJSON()).asObject();
1✔
583

584
            int totalCount = responseJSON.get("total_count").asInt();
1✔
585
            Collection<EmailAlias> emailAliases = new ArrayList<>(totalCount);
1✔
586
            JsonArray entries = responseJSON.get("entries").asArray();
1✔
587
            for (JsonValue value : entries) {
1✔
588
                JsonObject emailAliasJSON = value.asObject();
1✔
589
                emailAliases.add(new EmailAlias(emailAliasJSON));
1✔
590
            }
1✔
591

592
            return emailAliases;
1✔
593
        }
594
    }
595

596
    /**
597
     * Deletes a user from an enterprise account.
598
     *
599
     * @param notifyUser whether or not to send an email notification to the user that their account has been deleted.
600
     * @param force      whether or not this user should be deleted even if they still own files.
601
     */
602
    public void delete(boolean notifyUser, boolean force) {
603
        String queryString = new QueryStringBuilder()
1✔
604
            .appendParam("notify", String.valueOf(notifyUser))
1✔
605
            .appendParam("force", String.valueOf(force))
1✔
606
            .toString();
1✔
607

608
        performUserDelete(queryString);
1✔
609
    }
1✔
610

611
    /**
612
     * Deletes a user from an enterprise account. Uses API default values to determine if request should
613
     * be forced and if user should be notified.
614
     */
615
    public void delete() {
616
        performUserDelete("");
1✔
617
    }
1✔
618

619
    private void performUserDelete(String queryString) {
620
        URL url = USER_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), queryString, this.getID());
1✔
621
        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE");
1✔
622
        request.send().close();
1✔
623
    }
1✔
624

625
    /**
626
     * Updates the information about this user with any info fields that have been modified locally.
627
     *
628
     * <p>Note: This method is only available to enterprise admins.</p>
629
     *
630
     * @param info info the updated info.
631
     * @param fields the fields to retrieve. Leave this out for the standard fields.
632
     */
633
    public void updateInfo(BoxUser.Info info, String... fields) {
634
        QueryStringBuilder builder = new QueryStringBuilder();
1✔
635
        if (fields.length > 0) {
1✔
636
            builder.appendParam("fields", fields);
1✔
637
        }
638
        URL url = USER_URL_TEMPLATE.buildWithQuery(this.getAPI().getBaseURL(), builder.toString(), this.getID());
1✔
639
        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT");
1✔
640
        request.setBody(info.getPendingChanges());
1✔
641
        try (BoxJSONResponse response = request.send()) {
1✔
642
            JsonObject jsonObject = Json.parse(response.getJSON()).asObject();
1✔
643
            info.update(jsonObject);
1✔
644
        }
645
    }
1✔
646

647
    /**
648
     * Moves all the owned content from within one user’s folder into a new folder in another user's account.
649
     * You can move folders across users as long as the you have administrative permissions and the 'source'
650
     * user owns the folders. Per the documentation at the link below, this will move everything from the root
651
     * folder, as this is currently the only mode of operation supported.
652
     * <p>
653
     * See also <a href="https://developer.box.com/en/reference/put-users-id-folders-id/">https://developer.box.com/en/reference/put-users-id-folders-id/</a>
654
     *
655
     * @param destinationUserID the user id of the user that you wish to transfer content to.
656
     * @return info for the newly created folder.
657
     */
658
    public BoxFolder.Info transferContent(String destinationUserID) {
659
        URL url = MOVE_FOLDER_TO_USER_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID(), "0");
1✔
660
        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT");
1✔
661
        JsonObject destinationUser = new JsonObject();
1✔
662
        destinationUser.add("id", destinationUserID);
1✔
663
        JsonObject ownedBy = new JsonObject();
1✔
664
        ownedBy.add("owned_by", destinationUser);
1✔
665
        request.setBody(ownedBy.toString());
1✔
666
        try (BoxJSONResponse response = request.send()) {
1✔
667
            JsonObject responseJSON = Json.parse(response.getJSON()).asObject();
1✔
668
            BoxFolder movedFolder = new BoxFolder(this.getAPI(), responseJSON.get("id").asString());
1✔
669

670
            return movedFolder.new Info(responseJSON);
1✔
671
        }
672
    }
673

674
    /**
675
     * Writes avatar into specified {@link OutputStream}
676
     *
677
     * @param outputStream Stream where to write avatar.
678
     */
679
    public void downloadAvatar(OutputStream outputStream) {
680
        URL url = USER_AVATAR_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
1✔
681
        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
1✔
682
        writeStream(request.send(), outputStream);
1✔
683
    }
1✔
684

685
    /**
686
     * Retrieves the avatar of a user as an InputStream.
687
     *
688
     * @return InputStream representing the user avater.
689
     * @deprecated This method loads whole avatar image to memory.
690
     * Use {@link BoxUser#downloadAvatar(OutputStream)} to store avatar in file or memory.
691
     * That method uses very small buffer to store bytes in memory.
692
     */
693
    public InputStream getAvatar() {
694
        URL url = USER_AVATAR_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
1✔
695
        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
1✔
696
        BoxAPIResponse response = request.send();
1✔
697
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
1✔
698
            writeStream(response, outputStream);
1✔
699
            return new ByteArrayInputStream(outputStream.toByteArray());
1✔
700
        } catch (IOException e) {
×
701
            throw new RuntimeException("Error while closing stream", e);
×
702
        }
703
    }
704

705
    /**
706
     * Upload avatar image to user account. Supported formats are JPG and PNG.
707
     * The image size cannot exceed 1024 * 1024 pixels or 1MB.
708
     *
709
     * @param file File containg avatar image.
710
     * @return Avatar creation response.
711
     */
712
    public AvatarUploadResponse uploadAvatar(File file) {
713
        try {
714
            return uploadAvatar(new FileInputStream(file), file.getName());
1✔
715
        } catch (FileNotFoundException e) {
×
716
            throw new RuntimeException(e);
×
717
        }
718
    }
719

720
    /**
721
     * Upload avatar image to user account. Supported formats are JPG and PNG.
722
     * The image size cannot exceed 1024 * 1024 pixels or 1MB.
723
     *
724
     * @param file             {@link File} containg avatar image.
725
     * @param progressListener {@link ProgressListener} set if you want to track upload progress
726
     * @return Avatar creation response.
727
     */
728
    public AvatarUploadResponse uploadAvatar(File file, ProgressListener progressListener) {
729
        try {
730
            return uploadAvatar(new FileInputStream(file), file.getName(), progressListener);
×
731
        } catch (FileNotFoundException e) {
×
732
            throw new RuntimeException(e);
×
733
        }
734
    }
735

736
    /**
737
     * Upload avatar image to user account. Supported formats are JPG and PNG.
738
     * The image size cannot exceed 1024 * 1024 pixels or 1MB.
739
     *
740
     * @param content  {@link InputStream} containing image data
741
     * @param fileName file name with extention what will be used to determine content type
742
     * @return Avatar creation response.
743
     */
744
    public AvatarUploadResponse uploadAvatar(InputStream content, String fileName) {
745
        return uploadAvatar(content, fileName, null);
1✔
746
    }
747

748
    /**
749
     * Upload avatar image to user account. Supported formats are JPG and PNG.
750
     * The image size cannot exceed 1024 * 1024 pixels or 1MB.
751
     *
752
     * @param content          {@link InputStream} containing image data
753
     * @param fileName         file name with extention what will be used to determine content type
754
     * @param progressListener {@link ProgressListener} set if you want to track upload progress
755
     * @return Avatar creation response.
756
     */
757
    public AvatarUploadResponse uploadAvatar(InputStream content, String fileName, ProgressListener progressListener) {
758
        URL url = USER_AVATAR_TEMPLATE.build(getAPI().getBaseURL(), this.getID());
1✔
759
        BoxImageMultipartRequest request = new BoxImageMultipartRequest(getAPI(), url, "pic");
1✔
760
        request.setFile(content, fileName);
1✔
761

762
        BoxAPIResponse response = null;
1✔
763
        try {
764
            if (progressListener != null) {
1✔
765
                response = request.send(progressListener);
×
766
            } else {
767
                response = request.send();
1✔
768
            }
769

770
            return parseUploadAvatarResponse(response);
1✔
771
        } finally {
772
            Optional.ofNullable(response).ifPresent(BoxAPIResponse::close);
1✔
773
        }
774
    }
775

776
    /**
777
     * Removes avatar from user account.
778
     */
779
    public void deleteAvatar() {
780
        URL url = USER_AVATAR_TEMPLATE.build(getAPI().getBaseURL(), this.getID());
1✔
781
        BoxAPIRequest request = new BoxAPIRequest(getAPI(), url, DELETE);
1✔
782
        request.send().close();
1✔
783
    }
1✔
784

785
    private AvatarUploadResponse parseUploadAvatarResponse(BoxAPIResponse response) {
786
        JsonObject responseObject = Json.parse(response.bodyToString()).asObject();
1✔
787
        JsonObject picUrls = responseObject.get("pic_urls").asObject();
1✔
788
        return new AvatarUploadResponse(
1✔
789
            picUrls.getString("small", null),
1✔
790
            picUrls.getString("large", null),
1✔
791
            picUrls.getString("preview", null)
1✔
792
        );
793
    }
794

795
    /**
796
     * Enumerates the possible roles that a user can have within an enterprise.
797
     */
798
    public enum Role {
×
799
        /**
800
         * The user is an administrator of their enterprise.
801
         */
802
        ADMIN("admin"),
×
803

804
        /**
805
         * The user is a co-administrator of their enterprise.
806
         */
807
        COADMIN("coadmin"),
×
808

809
        /**
810
         * The user is a regular user within their enterprise.
811
         */
812
        USER("user");
×
813

814
        private final String jsonValue;
815

816
        Role(String jsonValue) {
×
817
            this.jsonValue = jsonValue;
×
818
        }
×
819

820
        static Role fromJSONValue(String jsonValue) {
NEW
821
            return Role.valueOf(jsonValue.toUpperCase(java.util.Locale.ROOT));
×
822
        }
823

824
        String toJSONValue() {
825
            return this.jsonValue;
×
826
        }
827
    }
828

829
    /**
830
     * Enumerates the possible statuses that a user's account can have.
831
     */
832
    public enum Status {
1✔
833
        /**
834
         * The user's account is active.
835
         */
836
        ACTIVE("active"),
1✔
837

838
        /**
839
         * The user's account is inactive.
840
         */
841
        INACTIVE("inactive"),
1✔
842

843
        /**
844
         * The user's account cannot delete or edit content.
845
         */
846
        CANNOT_DELETE_EDIT("cannot_delete_edit"),
1✔
847

848
        /**
849
         * The user's account cannot delete, edit, or upload content.
850
         */
851
        CANNOT_DELETE_EDIT_UPLOAD("cannot_delete_edit_upload");
1✔
852

853
        private final String jsonValue;
854

855
        Status(String jsonValue) {
1✔
856
            this.jsonValue = jsonValue;
1✔
857
        }
1✔
858

859
        static Status fromJSONValue(String jsonValue) {
860
            return Status.valueOf(jsonValue.toUpperCase(java.util.Locale.ROOT));
1✔
861
        }
862

863
        String toJSONValue() {
864
            return this.jsonValue;
×
865
        }
866
    }
867

868
    /**
869
     * Contains information about a BoxUser.
870
     */
871
    public class Info extends BoxCollaborator.Info {
872
        private String login;
873
        private Role role;
874
        private String language;
875
        private String timezone;
876
        private long spaceAmount;
877
        private long spaceUsed;
878
        private long maxUploadSize;
879
        private boolean canSeeManagedUsers;
880
        private boolean isSyncEnabled;
881
        private boolean isExternalCollabRestricted;
882
        private Status status;
883
        private String jobTitle;
884
        private String phone;
885
        private String address;
886
        private String avatarURL;
887
        private BoxNotificationEmail notificationEmail;
888
        private boolean isExemptFromDeviceLimits;
889
        private boolean isExemptFromLoginVerification;
890
        private boolean isPasswordResetRequired;
891
        private boolean isPlatformAccessOnly;
892
        private String externalAppUserId;
893
        private BoxEnterprise enterprise;
894
        private List<String> myTags;
895
        private String hostname;
896
        private Map<String, String> trackingCodes;
897

898
        /**
899
         * Constructs an empty Info object.
900
         */
901
        public Info() {
1✔
902
            super();
1✔
903
        }
1✔
904

905
        /**
906
         * Constructs an Info object by parsing information from a JSON string.
907
         *
908
         * @param json the JSON string to parse.
909
         */
910
        public Info(String json) {
×
911
            super(json);
×
912
        }
×
913

914
        Info(JsonObject jsonObject) {
1✔
915
            super(jsonObject);
1✔
916
        }
1✔
917

918
        @Override
919
        public BoxUser getResource() {
920
            return BoxUser.this;
1✔
921
        }
922

923
        /**
924
         * Gets the email address the user uses to login.
925
         *
926
         * @return the email address the user uses to login.
927
         */
928
        public String getLogin() {
929
            return this.login;
1✔
930
        }
931

932
        /**
933
         * Sets the email address the user uses to login. The new login must be one of the user's already confirmed
934
         * email aliases.
935
         *
936
         * @param login one of the user's confirmed email aliases.
937
         */
938
        public void setLogin(String login) {
939
            this.login = login;
1✔
940
            this.addPendingChange("login", login);
1✔
941
        }
1✔
942

943
        /**
944
         * Gets the user's enterprise role.
945
         *
946
         * @return the user's enterprise role.
947
         */
948
        public Role getRole() {
949
            return this.role;
×
950
        }
951

952
        /**
953
         * Sets the user's role in their enterprise.
954
         *
955
         * @param role the user's new role in their enterprise.
956
         */
957
        public void setRole(Role role) {
958
            this.role = role;
×
NEW
959
            this.addPendingChange("role", role.name().toLowerCase(java.util.Locale.ROOT));
×
960
        }
×
961

962
        /**
963
         * Gets the language of the user.
964
         *
965
         * @return the language of the user.
966
         */
967
        public String getLanguage() {
968
            return this.language;
×
969
        }
970

971
        /**
972
         * Sets the language of the user.
973
         *
974
         * @param language the new language of the user.
975
         */
976
        public void setLanguage(String language) {
977
            this.language = language;
×
978
            this.addPendingChange("language", language);
×
979
        }
×
980

981
        /**
982
         * Gets the timezone of the user.
983
         *
984
         * @return the timezone of the user.
985
         */
986
        public String getTimezone() {
987
            return this.timezone;
1✔
988
        }
989

990
        /**
991
         * Sets the timezone of the user.
992
         *
993
         * @param timezone the new timezone of the user.
994
         */
995
        public void setTimezone(String timezone) {
996
            this.timezone = timezone;
×
997
            this.addPendingChange("timezone", timezone);
×
998
        }
×
999

1000
        /**
1001
         * Gets the user's total available space in bytes.
1002
         *
1003
         * @return the user's total available space in bytes.
1004
         */
1005
        public long getSpaceAmount() {
1006
            return this.spaceAmount;
×
1007
        }
1008

1009
        /**
1010
         * Sets the user's total available space in bytes.
1011
         *
1012
         * @param spaceAmount the new amount of space available to the user in bytes, or -1 for unlimited storage.
1013
         */
1014
        public void setSpaceAmount(long spaceAmount) {
1015
            this.spaceAmount = spaceAmount;
×
1016
            this.addPendingChange("space_amount", spaceAmount);
×
1017
        }
×
1018

1019
        /**
1020
         * Gets the amount of space the user has used in bytes.
1021
         *
1022
         * @return the amount of space the user has used in bytes.
1023
         */
1024
        public long getSpaceUsed() {
1025
            return this.spaceUsed;
×
1026
        }
1027

1028
        /**
1029
         * Gets the maximum individual file size in bytes the user can have.
1030
         *
1031
         * @return the maximum individual file size in bytes the user can have.
1032
         */
1033
        public long getMaxUploadSize() {
1034
            return this.maxUploadSize;
×
1035
        }
1036

1037
        /**
1038
         * Gets the user's current account status.
1039
         *
1040
         * @return the user's current account status.
1041
         */
1042
        public Status getStatus() {
1043
            return this.status;
×
1044
        }
1045

1046
        /**
1047
         * Sets the user's current account status.
1048
         *
1049
         * @param status the user's new account status.
1050
         */
1051
        public void setStatus(Status status) {
1052
            this.status = status;
×
NEW
1053
            this.addPendingChange("status", status.name().toLowerCase(java.util.Locale.ROOT));
×
1054
        }
×
1055

1056
        /**
1057
         * Gets the job title of the user.
1058
         *
1059
         * @return the job title of the user.
1060
         */
1061
        public String getJobTitle() {
1062
            return this.jobTitle;
1✔
1063
        }
1064

1065
        /**
1066
         * Sets the job title of the user.
1067
         *
1068
         * @param jobTitle the new job title of the user.
1069
         */
1070
        public void setJobTitle(String jobTitle) {
1071
            this.jobTitle = jobTitle;
1✔
1072
            this.addPendingChange("job_title", jobTitle);
1✔
1073
        }
1✔
1074

1075
        /**
1076
         * Gets the phone number of the user.
1077
         *
1078
         * @return the phone number of the user.
1079
         */
1080
        public String getPhone() {
1081
            return this.phone;
1✔
1082
        }
1083

1084
        /**
1085
         * Sets the phone number of the user.
1086
         *
1087
         * @param phone the new phone number of the user.
1088
         */
1089
        public void setPhone(String phone) {
1090
            this.phone = phone;
1✔
1091
            this.addPendingChange("phone", phone);
1✔
1092
        }
1✔
1093

1094
        /**
1095
         * Gets the address of the user.
1096
         *
1097
         * @return the address of the user.
1098
         */
1099
        public String getAddress() {
1100
            return this.address;
×
1101
        }
1102

1103
        /**
1104
         * Sets the address of the user.
1105
         *
1106
         * @param address the new address of the user.
1107
         */
1108
        public void setAddress(String address) {
1109
            this.address = address;
×
1110
            this.addPendingChange("address", address);
×
1111
        }
×
1112

1113
        /**
1114
         * Gets the URL of the user's avatar.
1115
         *
1116
         * @return the URL of the user's avatar.
1117
         */
1118
        public String getAvatarURL() {
1119
            return this.avatarURL;
×
1120
        }
1121

1122
        /**
1123
         * Gets the user's alternate notification email address to which email notifications are sent.
1124
         *
1125
         * @return the user's notification email address.
1126
         */
1127
        public BoxNotificationEmail getNotificationEmail() {
1128
            return this.notificationEmail;
1✔
1129
        }
1130

1131
        /**
1132
         * Sets the user's notification email address.
1133
         *
1134
         * @param notificationEmail the user's new notification email address.
1135
         */
1136
        public void setNotificationEmail(BoxNotificationEmail notificationEmail) {
1137
            this.notificationEmail = notificationEmail;
×
1138
        }
×
1139

1140
        /**
1141
         * Gets the enterprise that the user belongs to.
1142
         *
1143
         * @return the enterprise that the user belongs to.
1144
         */
1145
        public BoxEnterprise getEnterprise() {
1146
            return this.enterprise;
×
1147
        }
1148

1149
        /**
1150
         * Removes the user from their enterprise and converts them to a standalone free user.
1151
         */
1152
        public void removeEnterprise() {
1153
            this.removeChildObject("enterprise");
×
1154
            this.enterprise = null;
×
1155
            this.addChildObject("enterprise", null);
×
1156
        }
×
1157

1158
        /**
1159
         * Gets whether or not the user can use Box Sync.
1160
         *
1161
         * @return true if the user can use Box Sync; otherwise false.
1162
         */
1163
        public boolean getIsSyncEnabled() {
1164
            return this.isSyncEnabled;
×
1165
        }
1166

1167
        /**
1168
         * Sets whether or not the user can use Box Sync.
1169
         *
1170
         * @param enabled whether or not the user can use Box Sync.
1171
         */
1172
        public void setIsSyncEnabled(boolean enabled) {
1173
            this.isSyncEnabled = enabled;
×
1174
            this.addPendingChange("is_sync_enabled", enabled);
×
1175
        }
×
1176

1177
        /**
1178
         * Gets whether this user is allowed or not to collaborate with users outside their enterprise.
1179
         *
1180
         * @return true if this user is not allowed to collaborate with users outside their enterprise; otherwise false.
1181
         */
1182
        public boolean getIsExternalCollabRestricted() {
1183
            return this.isExternalCollabRestricted;
×
1184
        }
1185

1186
        /**
1187
         * Sets whether this user is allowed or not to collaborate with users outside their enterprise.
1188
         *
1189
         * @param isExternalCollabRestricted whether the user is allowed to collaborate outside their enterprise.
1190
         */
1191
        public void setIsExternalCollabRestricted(boolean isExternalCollabRestricted) {
1192
            this.isExternalCollabRestricted = isExternalCollabRestricted;
×
1193
            this.addPendingChange("is_external_collab_restricted", isExternalCollabRestricted);
×
1194
        }
×
1195

1196
        /**
1197
         * Gets whether or not the user can see other enterprise users in their contact list.
1198
         *
1199
         * @return true if the user can see other enterprise users in their contact list; otherwise false.
1200
         */
1201
        public boolean getCanSeeManagedUsers() {
1202
            return this.canSeeManagedUsers;
×
1203
        }
1204

1205
        /**
1206
         * Sets whether or not the user can see other enterprise users in their contact list.
1207
         *
1208
         * @param canSeeManagedUsers whether or not the user can see other enterprise users in their contact list.
1209
         */
1210
        public void setCanSeeManagedUsers(boolean canSeeManagedUsers) {
1211
            this.canSeeManagedUsers = canSeeManagedUsers;
×
1212
            this.addPendingChange("can_see_managed_users", canSeeManagedUsers);
×
1213
        }
×
1214

1215
        /**
1216
         * Gets whether or not the user is exempt from enterprise device limits.
1217
         *
1218
         * @return true if the user is exempt from enterprise device limits; otherwise false.
1219
         */
1220
        public boolean getIsExemptFromDeviceLimits() {
1221
            return this.isExemptFromDeviceLimits;
×
1222
        }
1223

1224
        /**
1225
         * Sets whether or not the user is exempt from enterprise device limits.
1226
         *
1227
         * @param isExemptFromDeviceLimits whether or not the user is exempt from enterprise device limits.
1228
         */
1229
        public void setIsExemptFromDeviceLimits(boolean isExemptFromDeviceLimits) {
1230
            this.isExemptFromDeviceLimits = isExemptFromDeviceLimits;
×
1231
            this.addPendingChange("is_exempt_from_device_limits", isExemptFromDeviceLimits);
×
1232
        }
×
1233

1234
        /**
1235
         * Gets whether or not the user must use two-factor authentication.
1236
         *
1237
         * @return true if the user must use two-factor authentication; otherwise false.
1238
         */
1239
        public boolean getIsExemptFromLoginVerification() {
1240
            return this.isExemptFromLoginVerification;
×
1241
        }
1242

1243
        /**
1244
         * Sets whether or not the user must use two-factor authentication.
1245
         *
1246
         * @param isExemptFromLoginVerification whether or not the user must use two-factor authentication.
1247
         */
1248
        public void setIsExemptFromLoginVerification(boolean isExemptFromLoginVerification) {
1249
            this.isExemptFromLoginVerification = isExemptFromLoginVerification;
×
1250
            this.addPendingChange("is_exempt_from_login_verification", isExemptFromLoginVerification);
×
1251
        }
×
1252

1253
        /**
1254
         * Gets whether or not the user is required to reset password.
1255
         *
1256
         * @return true if the user is required to reset password; otherwise false.
1257
         */
1258
        public boolean getIsPasswordResetRequired() {
1259
            return this.isPasswordResetRequired;
×
1260
        }
1261

1262
        /**
1263
         * Sets whether or not the user is required to reset password.
1264
         *
1265
         * @param isPasswordResetRequired whether or not the user is required to reset password.
1266
         */
1267
        public void setIsPasswordResetRequired(boolean isPasswordResetRequired) {
1268
            this.isPasswordResetRequired = isPasswordResetRequired;
×
1269
            this.addPendingChange("is_password_reset_required", isPasswordResetRequired);
×
1270
        }
×
1271

1272
        /**
1273
         * Gets whether or not the user we are creating is an app user with Box Developer Edition.
1274
         *
1275
         * @return true if the new user is an app user for Box Developer Addition; otherwise false.
1276
         */
1277
        public boolean getIsPlatformAccessOnly() {
1278
            return this.isPlatformAccessOnly;
×
1279
        }
1280

1281
        /**
1282
         * Gets the external app user id that has been set for the app user.
1283
         *
1284
         * @return the external app user id.
1285
         */
1286
        public String getExternalAppUserId() {
1287
            return this.externalAppUserId;
×
1288
        }
1289

1290
        /**
1291
         * Sets the external app user id.
1292
         *
1293
         * @param externalAppUserId external app user id.
1294
         */
1295
        public void setExternalAppUserId(String externalAppUserId) {
1296
            this.externalAppUserId = externalAppUserId;
×
1297
            this.addPendingChange("external_app_user_id", externalAppUserId);
×
1298
        }
×
1299

1300
        /**
1301
         * Gets the tags for all files and folders owned by this user.
1302
         *
1303
         * @return the tags for all files and folders owned by this user.
1304
         */
1305
        public List<String> getMyTags() {
1306
            return this.myTags;
×
1307
        }
1308

1309
        /**
1310
         * Gets the root (protocol, subdomain, domain) of any links that need to be generated for this user.
1311
         *
1312
         * @return the root (protocol, subdomain, domain) of any links that need to be generated for this user.
1313
         */
1314
        public String getHostname() {
1315
            return this.hostname;
×
1316
        }
1317

1318
        /**
1319
         * Gets the tracking defined for each entity.
1320
         *
1321
         * @return a Map with tracking codes.
1322
         */
1323
        public Map<String, String> getTrackingCodes() {
1324
            return this.trackingCodes;
1✔
1325
        }
1326

1327
        /**
1328
         * Allows admin to set attributes specific for a group of users.
1329
         *
1330
         * @param trackingCodes a Map representing the user's new tracking codes
1331
         */
1332
        public void setTrackingCodes(Map<String, String> trackingCodes) {
1333
            this.trackingCodes = trackingCodes;
1✔
1334
            this.addPendingChange("tracking_codes", toTrackingCodesJson(this.trackingCodes));
1✔
1335
        }
1✔
1336

1337
        /**
1338
         * Allows the admin to append new tracking codes to the previous existing list.
1339
         *
1340
         * @param name  the name or `key` of the attribute to set.
1341
         * @param value the value of the attribute to set.
1342
         */
1343
        public void appendTrackingCodes(String name, String value) {
1344
            this.getTrackingCodes().put(name, value);
1✔
1345
            this.addPendingChange("tracking_codes", toTrackingCodesJson(this.trackingCodes));
1✔
1346
        }
1✔
1347

1348
        @SuppressWarnings("checkstyle:MissingSwitchDefault")
1349
        @Override
1350
        protected void parseJSONMember(JsonObject.Member member) {
1351
            super.parseJSONMember(member);
1✔
1352

1353
            JsonValue value = member.getValue();
1✔
1354
            String memberName = member.getName();
1✔
1355
            try {
1356
                switch (memberName) {
1✔
1357
                    case "login":
1358
                        this.login = value.asString();
1✔
1359
                        break;
1✔
1360
                    case "role":
1361
                        this.role = Role.fromJSONValue(value.asString());
×
1362
                        break;
×
1363
                    case "language":
1364
                        this.language = value.asString();
1✔
1365
                        break;
1✔
1366
                    case "timezone":
1367
                        this.timezone = value.asString();
1✔
1368
                        break;
1✔
1369
                    case "space_amount":
1370
                        this.spaceAmount = Double.valueOf(value.toString()).longValue();
1✔
1371
                        break;
1✔
1372
                    case "space_used":
1373
                        this.spaceUsed = Double.valueOf(value.toString()).longValue();
1✔
1374
                        break;
1✔
1375
                    case "max_upload_size":
1376
                        this.maxUploadSize = Double.valueOf(value.toString()).longValue();
1✔
1377
                        break;
1✔
1378
                    case "status":
1379
                        this.status = Status.fromJSONValue(value.asString());
1✔
1380
                        break;
1✔
1381
                    case "job_title":
1382
                        this.jobTitle = value.asString();
1✔
1383
                        break;
1✔
1384
                    case "phone":
1385
                        this.phone = value.asString();
1✔
1386
                        break;
1✔
1387
                    case "address":
1388
                        this.address = value.asString();
1✔
1389
                        break;
1✔
1390
                    case "avatar_url":
1391
                        this.avatarURL = value.asString();
1✔
1392
                        break;
1✔
1393
                    case "notification_email":
1394
                        if (value.isObject()) {
1✔
1395
                            this.notificationEmail = new BoxNotificationEmail(value.asObject());
1✔
1396
                        } else {
1397
                            this.notificationEmail = null;
1✔
1398
                        }
1399
                        break;
1✔
1400
                    case "can_see_managed_users":
1401
                        this.canSeeManagedUsers = value.asBoolean();
×
1402
                        break;
×
1403
                    case "is_sync_enabled":
1404
                        this.isSyncEnabled = value.asBoolean();
×
1405
                        break;
×
1406
                    case "is_external_collab_restricted":
1407
                        this.isExternalCollabRestricted = value.asBoolean();
×
1408
                        break;
×
1409
                    case "is_exempt_from_device_limits":
1410
                        this.isExemptFromDeviceLimits = value.asBoolean();
×
1411
                        break;
×
1412
                    case "is_exempt_from_login_verification":
1413
                        this.isExemptFromLoginVerification = value.asBoolean();
×
1414
                        break;
×
1415
                    case "is_password_reset_required":
1416
                        this.isPasswordResetRequired = value.asBoolean();
×
1417
                        break;
×
1418
                    case "is_platform_access_only":
1419
                        this.isPlatformAccessOnly = value.asBoolean();
×
1420
                        break;
×
1421
                    case "external_app_user_id":
1422
                        this.externalAppUserId = value.asString();
×
1423
                        break;
×
1424
                    case "enterprise":
1425
                        JsonObject jsonObject = value.asObject();
×
1426
                        if (this.enterprise == null) {
×
1427
                            this.enterprise = new BoxEnterprise(jsonObject);
×
1428
                        } else {
1429
                            this.enterprise.update(jsonObject);
×
1430
                        }
1431
                        break;
×
1432
                    case "my_tags":
1433
                        this.myTags = this.parseMyTags(value.asArray());
×
1434
                        break;
×
1435
                    case "hostname":
1436
                        this.hostname = value.asString();
×
1437
                        break;
×
1438
                    case "tracking_codes":
1439
                        this.trackingCodes = this.parseTrackingCodes(value.asArray());
1✔
1440
                        break;
1441
                }
1442
            } catch (Exception e) {
1✔
1443
                throw new BoxDeserializationException(memberName, value.toString(), e);
1✔
1444
            }
1✔
1445

1446
        }
1✔
1447

1448
        private List<String> parseMyTags(JsonArray jsonArray) {
1449
            List<String> myTags = new ArrayList<>(jsonArray.size());
×
1450
            for (JsonValue value : jsonArray) {
×
1451
                myTags.add(value.asString());
×
1452
            }
×
1453

1454
            return myTags;
×
1455
        }
1456

1457
        private Map<String, String> parseTrackingCodes(JsonArray jsonArray) {
1458
            Map<String, String> result = new HashMap<>();
1✔
1459
            if (jsonArray == null) {
1✔
1460
                return null;
×
1461
            }
1462
            List<JsonValue> valuesList = jsonArray.values();
1✔
1463
            for (JsonValue jsonValue : valuesList) {
1✔
1464
                JsonObject object = jsonValue.asObject();
1✔
1465
                result.put(object.get("name").asString(), object.get("value").asString());
1✔
1466
            }
1✔
1467
            return result;
1✔
1468
        }
1469
    }
1470
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc