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

smartsheet / smartsheet-java-sdk / #63

29 Apr 2026 07:51AM UTC coverage: 60.09% (-0.008%) from 60.098%
#63

push

github

web-flow
Adds the CONTRIBUTOR SeatType (#163)

* - adds the CONTRIBUTOR SeatType
- adds in test resources for a CONTRIBUTOR
- adds entry in CHANGELOG.md

* adds sdk tests for mocks as requested

* adds DowngradeSeatType updates for contributor and tests

* add support for displayContributorSeatType qp

* address MR feedback, simplifying test matrix

* style update on test to match previous implemented patterns

* updates listUser and listUserPlans tests to include displayContributorSeatType=true

10 of 13 new or added lines in 3 files covered. (76.92%)

4398 of 7319 relevant lines covered (60.09%)

0.6 hits per line

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

62.4
/src/main/java/com/smartsheet/api/internal/UserResourcesImpl.java
1
/*
2
 * Copyright (C) 2025 Smartsheet
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package com.smartsheet.api.internal;
18

19
import com.smartsheet.api.AuthorizationException;
20
import com.smartsheet.api.InvalidRequestException;
21
import com.smartsheet.api.ResourceNotFoundException;
22
import com.smartsheet.api.ServiceUnavailableException;
23
import com.smartsheet.api.SmartsheetException;
24
import com.smartsheet.api.UserResources;
25
import com.smartsheet.api.internal.http.HttpEntity;
26
import com.smartsheet.api.internal.http.HttpMethod;
27
import com.smartsheet.api.internal.http.HttpRequest;
28
import com.smartsheet.api.internal.http.HttpResponse;
29
import com.smartsheet.api.internal.util.QueryUtil;
30
import com.smartsheet.api.internal.util.Util;
31
import com.smartsheet.api.models.AlternateEmail;
32
import com.smartsheet.api.models.DeleteUserParameters;
33
import com.smartsheet.api.models.PagedResult;
34
import com.smartsheet.api.models.PaginationParameters;
35
import com.smartsheet.api.models.Result;
36
import com.smartsheet.api.models.Sheet;
37
import com.smartsheet.api.models.TokenPaginatedResult;
38
import com.smartsheet.api.models.User;
39
import com.smartsheet.api.models.UserPlan;
40
import com.smartsheet.api.models.UserProfile;
41
import com.smartsheet.api.models.enums.ListUserInclusion;
42
import com.smartsheet.api.models.enums.SeatType;
43
import com.smartsheet.api.models.enums.UpgradeSeatType;
44
import com.smartsheet.api.models.enums.DowngradeSeatType;
45
import com.smartsheet.api.models.enums.UserInclusion;
46

47
import java.io.File;
48
import java.io.FileInputStream;
49
import java.io.FileNotFoundException;
50
import java.io.InputStream;
51
import java.net.URLEncoder;
52
import java.nio.charset.StandardCharsets;
53
import java.text.SimpleDateFormat;
54
import java.util.Date;
55
import java.util.EnumSet;
56
import java.util.HashMap;
57
import java.util.List;
58
import java.util.Map;
59
import java.util.Set;
60
import java.util.Collections;
61

62
/**
63
 * This is the implementation of the UserResources.
64
 * <p>
65
 * Thread Safety: This class is thread safe because it is immutable and its base class is thread safe.
66
 */
67
public class UserResourcesImpl extends AbstractResources implements UserResources {
68

69
    private static final String USERS = "users";
70
    private static final String ALTERNATE_EMAILS = "alternateemails";
71
    public static final String PLANS = "/plans/";
72

73
    /**
74
     * Constructor.
75
     * <p>
76
     * Exceptions: - IllegalArgumentException : if any argument is null
77
     *
78
     * @param smartsheet the smartsheet
79
     */
80
    public UserResourcesImpl(SmartsheetImpl smartsheet) {
81
        super(smartsheet);
1✔
82
    }
1✔
83

84
    /**
85
     * List all users.
86
     * <p>
87
     * It mirrors to the following Smartsheet REST API method: GET /users
88
     *
89
     * @return the list of all users
90
     * @throws IllegalArgumentException    if any argument is null or empty string
91
     * @throws InvalidRequestException     if there is any problem with the REST API request
92
     * @throws AuthorizationException      if there is any problem with  the REST API authorization (access token)
93
     * @throws ResourceNotFoundException   if the resource cannot be found
94
     * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting)
95
     * @throws SmartsheetException         if there is any other error during the operation
96
     */
97
    public PagedResult<User> listUsers() throws SmartsheetException {
98
        return this.listUsersInternal(null, null, null, null, null, null);
1✔
99
    }
100

101
    /**
102
     * List all users.
103
     * <p>
104
     * It mirrors to the following Smartsheet REST API method: GET /users
105
     * <p>
106
     * Exceptions:
107
     *   - InvalidRequestException : if there is any problem with the REST API request
108
     *   - AuthorizationException : if there is any problem with the REST API authorization(access token)
109
     *   - ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
110
     *   - SmartsheetRestException : if there is any other REST API related error occurred during the operation
111
     *   - SmartsheetException : if there is any other error occurred during the operation
112
     *
113
     * @param pagination the object containing the pagination query parameters
114
     * @return all users (note that empty list will be returned if there is none)
115
     * @throws SmartsheetException the smartsheet exception
116
     */
117
    public PagedResult<User> listUsers(PaginationParameters pagination) throws SmartsheetException {
118
        return this.listUsersInternal(null, null, null, null, null, pagination);
1✔
119
    }
120

121
    /**
122
     * List all users.
123
     * <p>
124
     * It mirrors to the following Smartsheet REST API method: GET /users
125
     * <p>
126
     * Exceptions:
127
     * - InvalidRequestException : if there is any problem with the REST API request
128
     * - AuthorizationException : if there is any problem with the REST API authorization(access token)
129
     * - ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
130
     * - SmartsheetRestException : if there is any other REST API related error occurred during the operation
131
     * - SmartsheetException : if there is any other error occurred during the operation
132
     *
133
     * @param email      the list of email addresses
134
     * @param pagination the object containing the pagination query parameters
135
     * @return all users (note that empty list will be returned if there is none)
136
     * @throws SmartsheetException the smartsheet exception
137
     */
138
    public PagedResult<User> listUsers(Set<String> email, PaginationParameters pagination) throws SmartsheetException {
139
        return this.listUsersInternal(email, null, null, null, null, pagination);
1✔
140
    }
141

142
    /**
143
     * List all users.
144
     * <p>
145
     * It mirrors to the following Smartsheet REST API method: GET /users
146
     * <p>
147
     * Exceptions:
148
     * - InvalidRequestException : if there is any problem with the REST API request
149
     * - AuthorizationException : if there is any problem with the REST API authorization(access token)
150
     * - ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
151
     * - SmartsheetRestException : if there is any other REST API related error occurred during the operation
152
     * - SmartsheetException : if there is any other error occurred during the operation
153
     *
154
     * @param email      the list of email addresses
155
     * @param includes   elements to include in the response
156
     * @param pagination the object containing the pagination query parameters
157
     * @return all users (note that empty list will be returned if there is none)
158
     * @throws SmartsheetException the smartsheet exception
159
     */
160
    public PagedResult<User> listUsers(Set<String> email, EnumSet<ListUserInclusion> includes,
161
                                       PaginationParameters pagination) throws SmartsheetException {
162
        return this.listUsersInternal(email, includes, null, null, null, pagination);
1✔
163
    }
164

165
    /**
166
     * List all users with support for Seat Type and Plan ID. If planID or seatType is provided, then the response
167
     * will contain  planId, seatType, seatTypeLastChangedAt, isInternal, otherwise - not
168
     * <p>
169
     * It mirrors to the following Smartsheet REST API method: GET /users
170
     * <p>
171
     * Exceptions:
172
     *   - InvalidRequestException : if there is any problem with the REST API request
173
     *   - AuthorizationException : if there is any problem with the REST API authorization(access token)
174
     *   - ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
175
     *   - SmartsheetRestException : if there is any other REST API related error occurred during the operation
176
     *   - SmartsheetException : if there is any other error occurred during the operation
177
     *
178
     * @param email the list of email addresses
179
     * @param pagination the object containing the pagination query parameters
180
     * @param planId filtering all users part of the specific plan
181
     * @param seatType filter users by seat type
182
     * @return all users (note that empty list will be returned if there is none)
183
     * @throws SmartsheetException the smartsheet exception
184
     */
185
    @Override
186
    public PagedResult<User> listUsers(Set<String> email, Long planId,
187
                                       SeatType seatType, PaginationParameters pagination
188
                                       ) throws SmartsheetException {
189
        return this.listUsersInternal(email, null, planId, seatType, null, pagination);
1✔
190
    }
191

192
    /**
193
     * List all users with support for Seat Type and Plan ID. If planID or seatType is provided, then the response
194
     * will contain  planId, seatType, seatTypeLastChangedAt, isInternal, otherwise - not
195
     * <p>
196
     * It mirrors to the following Smartsheet REST API method: GET /users
197
     * <p>
198
     * Exceptions:
199
     *   - InvalidRequestException : if there is any problem with the REST API request
200
     *   - AuthorizationException : if there is any problem with the REST API authorization(access token)
201
     *   - ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
202
     *   - SmartsheetRestException : if there is any other REST API related error occurred during the operation
203
     *   - SmartsheetException : if there is any other error occurred during the operation
204
     *
205
     * @param email the list of email addresses
206
     * @param pagination the object containing the pagination query parameters
207
     * @param planId filtering all users part of the specific plan
208
     * @param seatType filter users by seat type
209
     * @param displayContributorSeatType if true, returns CONTRIBUTOR instead of VIEWER for eligible users
210
     * @return all users (note that empty list will be returned if there is none)
211
     * @throws SmartsheetException the smartsheet exception
212
     */
213
    @Override
214
    public PagedResult<User> listUsers(Set<String> email, Long planId,
215
                                       SeatType seatType, Boolean displayContributorSeatType,
216
                                       PaginationParameters pagination
217
                                       ) throws SmartsheetException {
NEW
218
        return this.listUsersInternal(email, null, planId, seatType, displayContributorSeatType, pagination);
×
219
    }
220

221
    /**
222
     * List all users with support for Seat Type and Plan ID. If planID or seatType is provided, then the response
223
     * will contain  planId, seatType, seatTypeLastChangedAt, isInternal, otherwise - not
224
     * <p>
225
     * It mirrors to the following Smartsheet REST API method: GET /users
226
     * <p>
227
     * Exceptions:
228
     *   - InvalidRequestException : if there is any problem with the REST API request
229
     *   - AuthorizationException : if there is any problem with the REST API authorization(access token)
230
     *   - ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
231
     *   - SmartsheetRestException : if there is any other REST API related error occurred during the operation
232
     *   - SmartsheetException : if there is any other error occurred during the operation
233
     *
234
     * @param email the list of email addresses
235
     * @param includes elements to include in the response
236
     * @param pagination the object containing the pagination query parameters
237
     * @param planId filtering all users part of the specific plan
238
     * @param seatType filter users by seat type
239
     * @param displayContributorSeatType if true, returns CONTRIBUTOR instead of VIEWER for eligible users
240
     * @return all users (note that empty list will be returned if there is none)
241
     * @throws SmartsheetException the smartsheet exception
242
     */
243
    private PagedResult<User> listUsersInternal(Set<String> email, EnumSet<ListUserInclusion> includes,
244
                                                Long planId, SeatType seatType, Boolean displayContributorSeatType,
245
                                                PaginationParameters pagination
246
                                                ) throws SmartsheetException {
247
        String path = USERS;
1✔
248
        Map<String, Object> parameters = new HashMap<>();
1✔
249

250
        if (pagination != null) {
1✔
251
            parameters = pagination.toHashMap();
1✔
252
        }
253

254
        if (email != null) {
1✔
255
            parameters.put("email", QueryUtil.generateCommaSeparatedList(email));
1✔
256
        }
257

258
        if (includes != null) {
1✔
259
            parameters.put("include", QueryUtil.generateCommaSeparatedList(includes));
1✔
260
        }
261

262
        // Seat type support
263
        if (planId != null) {
1✔
264
            parameters.put("planId", planId);
1✔
265
        }
266

267
        if (seatType != null) {
1✔
268
            parameters.put("seatType", seatType);
1✔
269
        }
270

271
        if (displayContributorSeatType != null) {
1✔
NEW
272
            parameters.put("displayContributorSeatType", displayContributorSeatType);
×
273
        }
274

275
        path += QueryUtil.generateUrl(null, parameters);
1✔
276
        return this.listResourcesWithWrapper(path, User.class);
1✔
277
    }
278

279
    /**
280
     * Add a user to the organization, without sending email.
281
     * <p>
282
     * It mirrors to the following Smartsheet REST API method: POST /users
283
     * <p>
284
     * Exceptions:
285
     * - IllegalArgumentException : if any argument is null
286
     * - InvalidRequestException : if there is any problem with the REST API request
287
     * - AuthorizationException : if there is any problem with the REST API authorization(access token)
288
     * - ResourceNotFoundException : if the resource can not be found
289
     * - ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
290
     * - SmartsheetRestException : if there is any other REST API related error occurred during the operation
291
     * - SmartsheetException : if there is any other error occurred during the operation
292
     *
293
     * @param user the user object limited to the following attributes: * admin * email * licensedSheetCreator
294
     * @return the user
295
     * @throws SmartsheetException the smartsheet exception
296
     */
297
    public User addUser(User user) throws SmartsheetException {
298
        return this.createResource(USERS, User.class, user);
1✔
299
    }
300

301
    /**
302
     * Add a user to the organization, without sending email.
303
     * <p>
304
     * It mirrors to the following Smartsheet REST API method: POST /users
305
     * <p>
306
     * Exceptions:
307
     * - IllegalArgumentException : if any argument is null
308
     * - InvalidRequestException : if there is any problem with the REST API request
309
     * - AuthorizationException : if there is any problem with the REST API authorization(access token)
310
     * - ResourceNotFoundException : if the resource can not be found
311
     * - ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
312
     * - SmartsheetRestException : if there is any other REST API related error occurred during the operation
313
     * - SmartsheetException : if there is any other error occurred during the operation
314
     *
315
     * @param user      the created user
316
     * @param sendEmail whether to send email
317
     * @return the user object limited to the following attributes: * admin * email * licensedSheetCreator
318
     * @throws SmartsheetException the smartsheet exception
319
     */
320
    public User addUser(User user, boolean sendEmail) throws SmartsheetException {
321
        return this.createResource("users?sendEmail=" + sendEmail, User.class, user);
1✔
322
    }
323

324
    /**
325
     * Get the current user.
326
     * <p>
327
     * It mirrors to the following Smartsheet REST API method: GET /users/{userId}
328
     *
329
     * @param userId the user id
330
     * @return the user
331
     * @throws IllegalArgumentException    if any argument is null or empty string
332
     * @throws InvalidRequestException     if there is any problem with the REST API request
333
     * @throws AuthorizationException      if there is any problem with  the REST API authorization (access token)
334
     * @throws ResourceNotFoundException   if the resource cannot be found
335
     * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting)
336
     * @throws SmartsheetException         if there is any other error during the operation
337
     */
338
    public UserProfile getUser(long userId) throws SmartsheetException {
339
        return this.getResource(USERS + "/" + userId, UserProfile.class);
1✔
340
    }
341

342
    /**
343
     * Get the current user.
344
     * <p>
345
     * It mirrors to the following Smartsheet REST API method: GET /users/me
346
     * <p>
347
     * Exceptions:
348
     * - InvalidRequestException : if there is any problem with the REST API request
349
     * - AuthorizationException : if there is any problem with the REST API authorization(access token)
350
     * - ResourceNotFoundException : if the resource can not be found
351
     * - ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
352
     * - SmartsheetRestException : if there is any other REST API related error occurred during the operation
353
     * - SmartsheetException : if there is any other error occurred during the operation
354
     *
355
     * @return the resource (note that if there is no such resource, this method will throw ResourceNotFoundException
356
     * rather than returning null).
357
     * @throws SmartsheetException the smartsheet exception
358
     */
359
    public UserProfile getCurrentUser() throws SmartsheetException {
360
        return this.getResource("users/me", UserProfile.class);
1✔
361
    }
362

363
    /**
364
     * <p>Get the current user.</p>
365
     *
366
     * <p>It mirrors to the following Smartsheet REST API method: GET /user/me</p>
367
     *
368
     * @param includes used to specify the optional objects to include.
369
     * @return the current user
370
     * @throws IllegalArgumentException    if any argument is null or empty string
371
     * @throws InvalidRequestException     if there is any problem with the REST API request
372
     * @throws AuthorizationException      if there is any problem with  the REST API authorization (access token)
373
     * @throws ResourceNotFoundException   if the resource cannot be found
374
     * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting)
375
     * @throws SmartsheetException         if there is any other error during the operation
376
     */
377
    public UserProfile getCurrentUser(EnumSet<UserInclusion> includes) throws SmartsheetException {
378
        String path = "users/me";
1✔
379

380
        Map<String, Object> parameters = new HashMap<>();
1✔
381
        parameters.put("include", QueryUtil.generateCommaSeparatedList(includes));
1✔
382

383
        path += QueryUtil.generateUrl(null, parameters);
1✔
384
        return this.getResource(path, UserProfile.class);
1✔
385
    }
386

387
    /**
388
     * List all organisation sheets.
389
     * <p>
390
     * It mirrors to the following Smartsheet REST API method: GET /users/sheets
391
     *
392
     * @param pagination the object containing the pagination query parameters
393
     * @return the list of all organisation sheets
394
     * @throws IllegalArgumentException    if any argument is null or empty string
395
     * @throws InvalidRequestException     if there is any problem with the REST API request
396
     * @throws AuthorizationException      if there is any problem with  the REST API authorization (access token)
397
     * @throws ResourceNotFoundException   if the resource cannot be found
398
     * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting)
399
     * @throws SmartsheetException         if there is any other error during the operation
400
     */
401
    public PagedResult<Sheet> listOrgSheets(PaginationParameters pagination, Date modifiedSince) throws SmartsheetException {
402
        String path = "users/sheets";
1✔
403

404
        Map<String, Object> parameters = new HashMap<>();
1✔
405
        if (pagination != null) {
1✔
406
            parameters = pagination.toHashMap();
1✔
407
        }
408
        if (modifiedSince != null) {
1✔
409
            String isoDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(modifiedSince);
×
410
            parameters.put("modifiedSince", isoDate);
×
411
        }
412
        path += QueryUtil.generateUrl(null, parameters);
1✔
413
        return this.listResourcesWithWrapper(path, Sheet.class);
1✔
414
    }
415

416
    public PagedResult<Sheet> listOrgSheets(PaginationParameters pagination) throws SmartsheetException {
417
        return this.listOrgSheets(pagination, null);
×
418
    }
419

420
    /**
421
     * List all user alternate emails.
422
     * <p>
423
     * It mirrors to the following Smartsheet REST API method: GET /users/{userId}/alternateemails
424
     *
425
     * @param userId     the id of the user
426
     * @param pagination the object containing the pagination query parameters
427
     * @return the list of all user alternate emails
428
     * @throws IllegalArgumentException    if any argument is null or empty string
429
     * @throws InvalidRequestException     if there is any problem with the REST API request
430
     * @throws AuthorizationException      if there is any problem with  the REST API authorization (access token)
431
     * @throws ResourceNotFoundException   if the resource cannot be found
432
     * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting)
433
     * @throws SmartsheetException         if there is any other error during the operation
434
     */
435
    public PagedResult<AlternateEmail> listAlternateEmails(long userId, PaginationParameters pagination) throws SmartsheetException {
436
        String path = USERS + "/" + userId + "/" + ALTERNATE_EMAILS;
1✔
437

438
        if (pagination != null) {
1✔
439
            path += pagination.toQueryString();
1✔
440
        }
441
        return this.listResourcesWithWrapper(path, AlternateEmail.class);
1✔
442
    }
443

444
    /**
445
     * Get alternate email.
446
     * <p>
447
     * It mirrors to the following Smartsheet REST API method: GET /users/{userId}/alternateemails/{alternateEmailId}
448
     *
449
     * @param userId     the id of the user
450
     * @param altEmailId the alternate email id for the alternate email to retrieve.
451
     * @return the resource (note that if there is no such resource, this method will throw
452
     * ResourceNotFoundException rather than returning null).
453
     * @throws IllegalArgumentException    if any argument is null or empty string
454
     * @throws InvalidRequestException     if there is any problem with the REST API request
455
     * @throws AuthorizationException      if there is any problem with  the REST API authorization (access token)
456
     * @throws ResourceNotFoundException   if the resource cannot be found
457
     * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting)
458
     * @throws SmartsheetException         if there is any other error during the operation
459
     */
460
    public AlternateEmail getAlternateEmail(long userId, long altEmailId) throws SmartsheetException {
461
        return this.getResource(USERS + "/" + userId + "/" + ALTERNATE_EMAILS + "/" + altEmailId, AlternateEmail.class);
1✔
462
    }
463

464
    /**
465
     * Add an alternate email.
466
     * <p>
467
     * It mirrors to the following Smartsheet REST API method: POST /users/{userId}/alternateemails
468
     *
469
     * @param userId    the id of the user
470
     * @param altEmails AlternateEmail alternate email address to add.
471
     * @return the resource (note that if there is no such resource, this method will throw
472
     * ResourceNotFoundException rather than returning null).
473
     * @throws IllegalArgumentException    if any argument is null or empty string
474
     * @throws InvalidRequestException     if there is any problem with the REST API request
475
     * @throws AuthorizationException      if there is any problem with  the REST API authorization (access token)
476
     * @throws ResourceNotFoundException   if the resource cannot be found
477
     * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting)
478
     * @throws SmartsheetException         if there is any other error during the operation
479
     */
480
    public List<AlternateEmail> addAlternateEmail(long userId, List<AlternateEmail> altEmails) throws SmartsheetException {
481
        Util.throwIfNull(altEmails);
1✔
482
        if (altEmails.size() == 0) {
1✔
483
            return altEmails;
1✔
484
        }
485
        return this.postAndReceiveList(USERS + "/" + userId + "/" + ALTERNATE_EMAILS, altEmails, AlternateEmail.class);
1✔
486
    }
487

488
    /**
489
     * Delete an alternate email.
490
     * <p>
491
     * It mirrors to the following Smartsheet REST API method: DELETE /users/{userId}/alternateemails/{alternateEmailId}
492
     *
493
     * @param userId     the id of the user
494
     * @param altEmailId the alternate email id for the alternate email to retrieve.
495
     * @throws IllegalArgumentException    if any argument is null or empty string
496
     * @throws InvalidRequestException     if there is any problem with the REST API request
497
     * @throws AuthorizationException      if there is any problem with  the REST API authorization (access token)
498
     * @throws ResourceNotFoundException   if the resource cannot be found
499
     * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting)
500
     * @throws SmartsheetException         if there is any other error during the operation
501
     */
502
    public void deleteAlternateEmail(long userId, long altEmailId) throws SmartsheetException {
503
        this.deleteResource(USERS + "/" + userId + "/" + ALTERNATE_EMAILS + "/" + altEmailId, AlternateEmail.class);
1✔
504
    }
1✔
505

506
    /**
507
     * Promote and alternate email to primary.
508
     *
509
     * @param userId     id of the user
510
     * @param altEmailId alternate email id
511
     * @return alternateEmail of the primary
512
     * @throws IllegalArgumentException    if any argument is null or empty string
513
     * @throws InvalidRequestException     if there is any problem with the REST API request
514
     * @throws AuthorizationException      if there is any problem with  the REST API authorization (access token)
515
     * @throws ResourceNotFoundException   if the resource cannot be found
516
     * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting)
517
     * @throws SmartsheetException         f there is any other error during the operation
518
     */
519
    public AlternateEmail promoteAlternateEmail(long userId, long altEmailId) throws SmartsheetException {
520

521
        HttpRequest request = createHttpRequest(smartsheet.getBaseURI().resolve(
×
522
                USERS + "/" + userId + "/" + ALTERNATE_EMAILS + "/" + altEmailId + "/makeprimary"), HttpMethod.POST);
523

524
        Object obj = null;
×
525
        try {
526
            HttpResponse response = this.smartsheet.getHttpClient().request(request);
×
527
            switch (response.getStatusCode()) {
×
528
                case 200:
529
                    obj = this.smartsheet.getJsonSerializer().deserializeResult(AlternateEmail.class,
×
530
                            response.getEntity().getContent());
×
531
                    break;
×
532
                default:
533
                    handleError(response);
×
534
            }
535
        } finally {
536
            smartsheet.getHttpClient().releaseConnection();
×
537
        }
538

539
        return (AlternateEmail) obj;
×
540
    }
541

542
    /**
543
     * Uploads a profile image for the specified user.
544
     *
545
     * @param userId   id of the user
546
     * @param file     path to the image file
547
     * @param fileType content type of the image file
548
     * @return user
549
     * @throws IllegalArgumentException    if any argument is null or empty string
550
     * @throws InvalidRequestException     if there is any problem with the REST API request
551
     * @throws AuthorizationException      if there is any problem with  the REST API authorization (access token)
552
     * @throws ResourceNotFoundException   if the resource cannot be found
553
     * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting)
554
     * @throws SmartsheetException         f there is any other error during the operation
555
     */
556
    public User addProfileImage(long userId, String file, String fileType) throws SmartsheetException, FileNotFoundException {
557
        return attachProfileImage(USERS + "/" + userId + "/profileimage", file, fileType);
×
558
    }
559

560
    private User attachProfileImage(String path, String file, String contentType) throws SmartsheetException, FileNotFoundException {
561
        Util.throwIfNull(file);
×
562

563
        if (contentType == null) {
×
564
            contentType = "application/octet-stream";
×
565
        }
566

567
        Map<String, Object> parameters = new HashMap<>();
×
568
        path += QueryUtil.generateUrl(null, parameters);
×
569

570
        HttpRequest request = createHttpRequest(this.smartsheet.getBaseURI().resolve(path), HttpMethod.POST);
×
571
        String attachmentHeaderValue = "attachment; filename=\"" + URLEncoder.encode(file, StandardCharsets.UTF_8) + "\"";
×
572
        request.getHeaders().put("Content-Disposition", attachmentHeaderValue);
×
573

574
        File f = new File(file);
×
575
        InputStream is = new FileInputStream(f);
×
576

577
        HttpEntity entity = new HttpEntity();
×
578
        entity.setContentType(contentType);
×
579
        entity.setContent(is);
×
580
        entity.setContentLength(f.length());
×
581
        request.setEntity(entity);
×
582

583
        User obj = null;
×
584
        try {
585
            HttpResponse response = this.smartsheet.getHttpClient().request(request);
×
586
            switch (response.getStatusCode()) {
×
587
                case 200:
588
                    obj = this.smartsheet.getJsonSerializer().deserializeResult(User.class,
×
589
                            response.getEntity().getContent()).getResult();
×
590
                    break;
×
591
                default:
592
                    handleError(response);
×
593
            }
594
        } finally {
595
            smartsheet.getHttpClient().releaseConnection();
×
596
        }
597

598
        return obj;
×
599
    }
600

601
    /**
602
     * <p>Update a user.</p>
603
     *
604
     * <p>It mirrors to the following Smartsheet REST API method: PUT /user/{id}</p>
605
     *
606
     * @param user the user to update
607
     * @return the updated user
608
     * @throws IllegalArgumentException    if any argument is null or empty string
609
     * @throws InvalidRequestException     if there is any problem with the REST API request
610
     * @throws AuthorizationException      if there is any problem with  the REST API authorization (access token)
611
     * @throws ResourceNotFoundException   if the resource cannot be found
612
     * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting)
613
     * @throws SmartsheetException         if there is any other error during the operation
614
     */
615
    @Override
616
    public User updateUser(User user) throws SmartsheetException {
617
        return this.updateResource(USERS + "/" + user.getId(), User.class, user);
1✔
618
    }
619

620
    /**
621
     * <p>Fetch all user's plans.</p>
622
     *
623
     * <p>It mirrors to the following Smartsheet REST API method: GET /users/{userId}/plans</p>
624
     *
625
     * @param userId the id of the user whose plans to fetch
626
     * @param lastKey lastKey from previous response to get next page of results
627
     * @return UserPlansResponse json response
628
     * @throws IllegalArgumentException    if any argument is null or empty string
629
     * @throws InvalidRequestException     if there is any problem with the REST API request
630
     * @throws AuthorizationException      if there is any problem with  the REST API authorization (access token)
631
     * @throws ResourceNotFoundException   if the resource cannot be found
632
     * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting)
633
     * @throws SmartsheetException         if there is any other error during the operation
634
     */
635
    @Override
636
    public TokenPaginatedResult<UserPlan> listUserPlans(long userId, String lastKey, Long maxItems) throws SmartsheetException {
637
        return listUserPlans(userId, lastKey, maxItems, null);
1✔
638
    }
639

640
    /**
641
     * <p>Fetch all user's plans.</p>
642
     *
643
     * <p>It mirrors to the following Smartsheet REST API method: GET /users/{userId}/plans</p>
644
     *
645
     * @param userId the id of the user whose plans to fetch
646
     * @param lastKey lastKey from previous response to get next page of results
647
     * @param maxItems maximum number of items to return
648
     * @param displayContributorSeatType if true, returns CONTRIBUTOR instead of VIEWER for eligible users
649
     * @return UserPlansResponse json response
650
     * @throws IllegalArgumentException    if any argument is null or empty string
651
     * @throws InvalidRequestException     if there is any problem with the REST API request
652
     * @throws AuthorizationException      if there is any problem with  the REST API authorization (access token)
653
     * @throws ResourceNotFoundException   if the resource cannot be found
654
     * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting)
655
     * @throws SmartsheetException         if there is any other error during the operation
656
     */
657
    @Override
658
    public TokenPaginatedResult<UserPlan> listUserPlans(
659
            long userId,
660
            String lastKey,
661
            Long maxItems,
662
            Boolean displayContributorSeatType
663
    ) throws SmartsheetException {
664

665
        String path = USERS + "/" + userId + "/plans";
1✔
666
        Map<String, Object> parameters = new HashMap<>();
1✔
667

668
        if (lastKey != null) {
1✔
669
            parameters.put("lastKey", lastKey);
1✔
670
        }
671

672
        if (maxItems != null) {
1✔
673
            parameters.put("maxItems", maxItems);
1✔
674
        }
675

676
        if (displayContributorSeatType != null) {
1✔
NEW
677
            parameters.put("displayContributorSeatType", displayContributorSeatType);
×
678
        }
679

680
        path += QueryUtil.generateUrl(null, parameters);
1✔
681
        return this.listResourcesWithTokenPagination(path, UserPlan.class);
1✔
682
    }
683

684
    /**
685
     * <p>Remove's a user from a plan.</p>
686
     *
687
     * <p>It mirrors to the following Smartsheet REST API method: DELETE /2.0/users/{userId}/plans/{planId}</p>
688
     *
689
     * @param userId the id of the user whose plans to fetch
690
     * @param planId the id of the plan from which to remove the user
691
     * @throws IllegalArgumentException    if any argument is null or empty string
692
     * @throws InvalidRequestException     if there is any problem with the REST API request
693
     * @throws AuthorizationException      if there is any problem with  the REST API authorization (access token)
694
     * @throws ResourceNotFoundException   if the resource cannot be found
695
     * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting)
696
     * @throws SmartsheetException         if there is any other error during the operation
697
     */
698
    @Override
699
    public void removeUserFromPlan(long userId, long planId) throws SmartsheetException {
700
        deleteResource(USERS + "/" + userId + PLANS + planId, Object.class);
1✔
701
    }
1✔
702

703
    /**
704
     * <p>Upgrades a user's seat type.</p>
705
     *
706
     * <p>It mirrors to the following Smartsheet REST API method: POST /users/{userId}/plans/{planId}/upgrade</p>
707
     * @param userId the ID of the user to upgrade
708
     * @param planId the ID of the plan to upgrade to
709
     * @param seatType the new seat type for the user
710
     * @throws IllegalArgumentException if any argument is null or empty string
711
     * @throws InvalidRequestException if there is any problem with the REST API request
712
     * @throws AuthorizationException if there is any problem with the REST API authorization
713
     * @throws ResourceNotFoundException if the resource cannot be found
714
     * @throws ServiceUnavailableException if the REST API service is not available
715
     * @throws SmartsheetException if there is any other error during the operation
716
     */
717
    @Override
718
    public void upgradeUser(long userId, long planId, UpgradeSeatType seatType) throws SmartsheetException {
719
        if (seatType != null) {
1✔
720
            changeSeatType(seatType.name(), USERS + "/" + userId + PLANS + planId + "/upgrade");
1✔
721
            return;
1✔
722
        }
723
        changeSeatType(null, USERS + "/" + userId + PLANS + planId + "/upgrade");
×
724
    }
×
725

726
    /**
727
     * <p>Downgrades a user's seat type.</p>
728
     *
729
     * <p>It mirrors to the following Smartsheet REST API method: POST /users/{userId}/plans/{planId}/downgrade</p>
730
     * @param userId the ID of the user to downgrade
731
     * @param planId the ID of the plan to downgrade to
732
     * @param seatType the new seat type for the user
733
     * @throws IllegalArgumentException if any argument is null or empty string
734
     * @throws InvalidRequestException if there is any problem with the REST API request
735
     * @throws AuthorizationException if there is any problem with the REST API authorization
736
     * @throws ResourceNotFoundException if the resource cannot be found
737
     * @throws ServiceUnavailableException if the REST API service is not available
738
     * @throws SmartsheetException if there is any other error during the operation
739
     */
740
    @Override
741
    public void downgradeUser(long userId, long planId, DowngradeSeatType seatType) throws SmartsheetException {
742
        Util.throwIfNull(seatType);
1✔
743
        changeSeatType(seatType.name(), USERS + "/" + userId + PLANS + planId + "/downgrade");
1✔
744
    }
1✔
745

746
    private void changeSeatType(String seatType, String path) throws SmartsheetException {
747
        Map<String, String> body = Collections.emptyMap();
1✔
748
        if (seatType != null) {
1✔
749
            body = Map.of("seatType", seatType);
1✔
750
        }
751
        createResource(path, Result.class, body);
1✔
752
    }
1✔
753

754
    /**
755
     * <p>Reactivates a user.</p>
756
     *
757
     * <p>Reactivates the user associated with the current Smartsheet plan, restoring the user's access to
758
     * Smartsheet, owned items, and shared items.</p>
759
     *
760
     * <p>Important: You can reactivate the user only if that user has been deactivated for less than thirty (30) days.</p>
761
     *
762
     * <p>It mirrors to the following Smartsheet REST API method: POST /users/{userId}/reactivate</p>
763
     *
764
     * @param userId the id of the user to reactivate
765
     * @throws IllegalArgumentException    if any argument is null or empty string
766
     * @throws InvalidRequestException     if there is any problem with the REST API request (e.g., user email belongs to ISP domain)
767
     * @throws AuthorizationException      if there is any problem with the REST API authorization (access token)
768
     * @throws ResourceNotFoundException   if the resource cannot be found
769
     * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting)
770
     * @throws SmartsheetException         if there is any other error during the operation
771
     */
772
    @Override
773
    public void reactivateUser(long userId) throws SmartsheetException {
774
        createResource(USERS + "/" + userId + "/reactivate", Result.class, Collections.emptyMap());
×
775
    }
×
776

777
    /**
778
     * <p>Deactivates a user.</p>
779
     *
780
     * <p>Deactivates the user associated with the current Smartsheet plan, blocking the user from using Smartsheet in any way.
781
     * Deactivating a user does not affect their existing permissions on owned or shared items.</p>
782
     *
783
     * <p>It mirrors to the following Smartsheet REST API method: POST /users/{userId}/deactivate</p>
784
     *
785
     * @param userId the id of the user to deactivate
786
     * @throws IllegalArgumentException    if any argument is null or empty string
787
     * @throws InvalidRequestException     if there is any problem with the REST API request (e.g., user email belongs to ISP domain or user is managed by external source)
788
     * @throws AuthorizationException      if there is any problem with the REST API authorization (access token)
789
     * @throws ResourceNotFoundException   if the resource cannot be found
790
     * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting)
791
     * @throws SmartsheetException         if there is any other error during the operation
792
     */
793
    @Override
794
    public void deactivateUser(long userId) throws SmartsheetException {
795
        createResource(USERS + "/" + userId + "/deactivate", Result.class, Collections.emptyMap());
×
796
    }
×
797

798
    @Override
799
    public void deleteUser(long userId, DeleteUserParameters parameters) throws SmartsheetException {
800
        String path = USERS + "/" + userId;
1✔
801

802
        if (parameters != null) {
1✔
803
            path += parameters.toQueryString();
1✔
804
        }
805

806
        this.deleteResource(path, User.class);
1✔
807
    }
1✔
808
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc