box-node-sdk 1.9.0 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,14 @@
3
3
  */
4
4
 
5
5
  'use strict';
6
+ // -----------------------------------------------------------------------------
7
+ // Typedefs
8
+ // -----------------------------------------------------------------------------
9
+
10
+ /**
11
+ * A representation request type constant
12
+ * @typedef {string} FileRepresentationType Different representations we can request from reps endpoint
13
+ */
6
14
 
7
15
  // -----------------------------------------------------------------------------
8
16
  // Requirements
@@ -46,18 +54,23 @@ var lockTypes = {
46
54
  * Returns the multipart form value for file upload metadata.
47
55
  * @param {string} parentFolderID - the ID of the parent folder to upload to
48
56
  * @param {string} filename - the file name that the uploaded file should have
57
+ * @param {Object} [options] - Optional metadata
49
58
  * @returns {Object} - the form value expected by the API for the 'metadata' key
50
59
  * @private
51
60
  */
52
- function createFileMetadataFormData(parentFolderID, filename) {
61
+ function createFileMetadataFormData(parentFolderID, filename, options) {
53
62
  // Although the filename and parent folder ID can be specified without using a
54
63
  // metadata form field, Platform has recommended that we use the metadata form
55
64
  // field to specify these parameters (one benefit is that UTF-8 characters can
56
65
  // be specified in the filename).
57
- return JSON.stringify({
66
+ var metadata = {
58
67
  name: filename,
59
68
  parent: { id: parentFolderID }
60
- });
69
+ };
70
+
71
+ Object.assign(metadata, options);
72
+
73
+ return JSON.stringify(metadata);
61
74
  }
62
75
 
63
76
  /**
@@ -145,11 +158,11 @@ Files.prototype.getDownloadURL = function(fileID, qs, callback) {
145
158
  case httpStatusCodes.FOUND:
146
159
  return response.headers.location;
147
160
 
148
- // 202 - Download isn't ready yet.
161
+ // 202 - Download isn't ready yet.
149
162
  case httpStatusCodes.ACCEPTED:
150
163
  throw errors.buildResponseError(response, 'Download not ready at this time');
151
164
 
152
- // Unexpected Response
165
+ // Unexpected Response
153
166
  default:
154
167
  throw errors.buildUnexpectedResponseError(response);
155
168
  }
@@ -176,7 +189,7 @@ Files.prototype.getReadStream = function(fileID, qs, callback) {
176
189
  // Get the download URL to download from
177
190
  return this.getDownloadURL(fileID, qs)
178
191
  // Return a read stream to download the file
179
- .then(url => this.client.get(url, {streaming: true}))
192
+ .then(url => this.client.get(url, { streaming: true }))
180
193
  .asCallback(callback);
181
194
  };
182
195
 
@@ -219,15 +232,15 @@ Files.prototype.getThumbnail = function(fileID, qs, callback) {
219
232
  location: response.headers.location
220
233
  };
221
234
 
222
- // 200 - Thumbnail image recieved
223
- // return the thumbnail file
235
+ // 200 - Thumbnail image recieved
236
+ // return the thumbnail file
224
237
  case httpStatusCodes.OK:
225
238
  return {
226
239
  statusCode: response.statusCode,
227
240
  file: response.body
228
241
  };
229
242
 
230
- // Unexpected Response
243
+ // Unexpected Response
231
244
  default:
232
245
  throw errors.buildUnexpectedResponseError(response);
233
246
  }
@@ -288,20 +301,20 @@ Files.prototype.update = function(fileID, options, callback) {
288
301
  */
289
302
  Files.prototype.addToCollection = function(fileID, collectionID, callback) {
290
303
 
291
- return this.get(fileID, {fields: 'collections'})
304
+ return this.get(fileID, { fields: 'collections' })
292
305
  .then(data => {
293
306
 
294
307
  var collections = data.collections || [];
295
308
 
296
309
  // Convert to correct format
297
- collections = collections.map(c => ({id: c.id}));
310
+ collections = collections.map(c => ({ id: c.id }));
298
311
 
299
312
  if (!collections.find(c => c.id === collectionID)) {
300
313
 
301
- collections.push({id: collectionID});
314
+ collections.push({ id: collectionID });
302
315
  }
303
316
 
304
- return this.update(fileID, {collections});
317
+ return this.update(fileID, { collections });
305
318
  })
306
319
  .asCallback(callback);
307
320
  };
@@ -319,14 +332,14 @@ Files.prototype.addToCollection = function(fileID, collectionID, callback) {
319
332
  */
320
333
  Files.prototype.removeFromCollection = function(fileID, collectionID, callback) {
321
334
 
322
- return this.get(fileID, {fields: 'collections'})
335
+ return this.get(fileID, { fields: 'collections' })
323
336
  .then(data => {
324
337
 
325
338
  var collections = data.collections || [];
326
339
  // Convert to correct object format and remove the specified collection
327
- collections = collections.map(c => ({id: c.id})).filter(c => c.id !== collectionID);
340
+ collections = collections.map(c => ({ id: c.id })).filter(c => c.id !== collectionID);
328
341
 
329
- return this.update(fileID, {collections});
342
+ return this.update(fileID, { collections });
330
343
  })
331
344
  .asCallback(callback);
332
345
  };
@@ -510,14 +523,24 @@ Files.prototype.promoteVersion = function(fileID, versionID, callback) {
510
523
  * @param {string} filename - the file name that the uploaded file should have
511
524
  * @param {string|Buffer|ReadStream} content - the content of the file. It can be a string, a Buffer, or a read stream
512
525
  * (like that returned by fs.createReadStream()).
526
+ * @param {Object} [options] - Optional parameters
527
+ * @param {string} [options.content_created_at] - RFC 3339 timestamp when the file was created
528
+ * @param {string} [options.content_modified_at] - RFC 3339 timestamp when the file was last modified
513
529
  * @param {Function} [callback] - called with data about the upload if successful, or an error if the
514
530
  * upload failed
515
531
  * @returns {Promise<Object>} A promise resolving to the uploaded file
516
532
  */
517
- Files.prototype.uploadFile = function(parentFolderID, filename, content, callback) {
533
+ Files.prototype.uploadFile = function(parentFolderID, filename, content, options, callback) {
534
+
535
+ // Shuffle around optional parameter
536
+ if (typeof options === 'function') {
537
+ callback = options;
538
+ options = {};
539
+ }
540
+
518
541
  var apiPath = urlPath(BASE_PATH, '/content'),
519
542
  multipartFormData = {
520
- attributes: createFileMetadataFormData(parentFolderID, filename),
543
+ attributes: createFileMetadataFormData(parentFolderID, filename, options),
521
544
  content: createFileContentFormData(content)
522
545
  };
523
546
 
@@ -534,16 +557,30 @@ Files.prototype.uploadFile = function(parentFolderID, filename, content, callbac
534
557
  * @param {string} fileID - the id of the file to upload a new version of
535
558
  * @param {string|Buffer|Stream} content - the content of the file. It can be a string, a Buffer, or a read stream
536
559
  * (like that returned by fs.createReadStream()).
560
+ * @param {Object} [options] - Optional parameters
561
+ * @param {string} [options.content_modified_at] - RFC 3339 timestamp when the file was last modified
562
+ * @param {string} [options.name] - A new name for the file
537
563
  * @param {Function} [callback] - called with data about the upload if successful, or an error if the
538
564
  * upload failed
539
565
  * @returns {Promise<Object>} A promise resolving to the uploaded file
540
566
  */
541
- Files.prototype.uploadNewFileVersion = function(fileID, content, callback) {
567
+ Files.prototype.uploadNewFileVersion = function(fileID, content, options, callback) {
568
+
569
+ // Shuffle around optional parameter
570
+ if (typeof options === 'function') {
571
+ callback = options;
572
+ options = {};
573
+ }
574
+
542
575
  var apiPath = urlPath(BASE_PATH, fileID, '/content'),
543
576
  multipartFormData = {
544
577
  content: createFileContentFormData(content)
545
578
  };
546
579
 
580
+ if (options) {
581
+ multipartFormData.attributes = JSON.stringify(options);
582
+ }
583
+
547
584
  return this.client.wrapWithDefaultHandler(this.client.upload)(apiPath, null, multipartFormData, callback);
548
585
  };
549
586
 
@@ -1105,7 +1142,7 @@ Files.prototype.commitUploadSession = function(sessionID, fileHash, options, cal
1105
1142
  .then(() => {
1106
1143
 
1107
1144
  // Ensure we don't have to fetch parts from the API again on retry
1108
- options = Object.assign({}, options, {parts: params.body.parts});
1145
+ options = Object.assign({}, options, { parts: params.body.parts });
1109
1146
  return this.commitUploadSession(sessionID, fileHash, options);
1110
1147
  });
1111
1148
  }
@@ -1242,6 +1279,61 @@ Files.prototype.getCollaborations = function(fileID, options, callback) {
1242
1279
  return this.client.wrapWithDefaultHandler(this.client.get)(apiPath, params, callback);
1243
1280
  };
1244
1281
 
1282
+ /**
1283
+ * Enum of valid x-rep- hint values for generating representation info
1284
+ *
1285
+ * @readonly
1286
+ * @enum {FileRepresentationType}
1287
+ */
1288
+ Files.prototype.representation = {
1289
+ PDF: '[pdf]',
1290
+ THUMBNAIL: '[jpg?dimensions=320x320]',
1291
+ IMAGE_MEDIUM: '[jpg?dimensions=1024x1024][png?dimensions=1024x1024]',
1292
+ IMAGE_LARGE: '[jpg?dimensions=2048x2048][png?dimensions=2048x2048]',
1293
+ EXTRACTED_TEXT: '[extracted_text]'
1294
+ };
1295
+ /**
1296
+ * Requests information for all representation objects generated for a specific Box file
1297
+ *
1298
+ * API Endpoint: '/files/:fileID?fields=representations'
1299
+ * Method : GET
1300
+ *
1301
+ * @param {string} fileID - Box ID of the file being requested
1302
+ * @param {client.files.representation} representationType - The x-rep-hints value the application should create a
1303
+ * representation for. This value can either come from FileRepresentationType enum or manually created
1304
+ * @param {Function} [callback] - Passed an array of representaton objects if successful
1305
+ * @returns {Promise<Object>} A promise resolving to the representation response objects
1306
+ */
1307
+ Files.prototype.getRepresentationInfo = function(fileID, representationType, callback) {
1308
+ var params = {
1309
+ qs: {
1310
+ fields: 'representations'
1311
+ },
1312
+ headers: {
1313
+ 'x-rep-hints': representationType
1314
+ }
1315
+ };
1316
+ var apiPath = urlPath(BASE_PATH, fileID);
1317
+
1318
+ return this.client.get(apiPath, params)
1319
+ .then(response => {
1320
+ switch (response.statusCode) {
1321
+ // 202 - A Box file representation will be generated, but is not ready yet
1322
+ case httpStatusCodes.ACCEPTED:
1323
+ throw errors.buildResponseError(response, 'Representation not ready at this time');
1324
+
1325
+ // 200 - A Boxfile representation generated successfully
1326
+ // return the representation object
1327
+ case httpStatusCodes.OK:
1328
+ return response.body.representations;
1329
+
1330
+ // Unexpected Response
1331
+ default:
1332
+ throw errors.buildUnexpectedResponseError(response);
1333
+ }
1334
+ })
1335
+ .asCallback(callback);
1336
+ };
1245
1337
  /**
1246
1338
  * @module box-node-sdk/lib/managers/files
1247
1339
  * @see {@Link Files}
@@ -165,6 +165,24 @@ Metadata.prototype = {
165
165
  };
166
166
 
167
167
  return this.client.wrapWithDefaultHandler(this.client.put)(apiPath, params, callback);
168
+ },
169
+
170
+ /**
171
+ * Delete a metadata template from an enterprise.
172
+ *
173
+ * API Endpoint: '/metadata_templates/:scope/:template/schema'
174
+ * Method: DELETE
175
+ *
176
+ * @param {string} scope - The scope of the template to delete
177
+ * @param {string} template - The template to delete
178
+ * @param {Function} [callback] - Passed empty response body if successful, err otherwise
179
+ * @returns {Promise<void>} A promise resolving to nothing
180
+ * @see {@link https://docs.box.com/reference#delete-metadata-schema}
181
+ */
182
+ deleteTemplate: function(scope, template, callback) {
183
+
184
+ var apiPath = urlPath(BASE_PATH, scope, template, SCHEMA_SUBRESOURCE);
185
+ return this.client.wrapWithDefaultHandler(this.client.del)(apiPath, callback);
168
186
  }
169
187
  };
170
188
 
@@ -23,9 +23,9 @@ var urlPath = require('../util/url-path'),
23
23
  * @property {Object} filters Key/value filters against individual metadata template properties
24
24
  */
25
25
 
26
- /** @typedef {string} SearchScope */
26
+ /** @typedef {string} SearchScope */
27
27
 
28
- /** @typedef {string} SearchTrashContent */
28
+ /** @typedef {string} SearchTrashContent */
29
29
 
30
30
  // -----------------------------------------------------------------------------
31
31
  // Private
@@ -0,0 +1,307 @@
1
+ /**
2
+ * @fileoverview Manager for the Box Terms of Service Resource
3
+ */
4
+
5
+ 'use strict';
6
+ // -----------------------------------------------------------------------------
7
+ // Typedefs
8
+ // -----------------------------------------------------------------------------
9
+
10
+ /**
11
+ * Terms of service parameter constant
12
+ * @typedef {string} TermsOfServicesStatus Determines whether the terms of service created is currently enabled or disabled
13
+ * @typedef {string} TermsOfServicesType Determines whether the terms of service is for internal users or users outside of the enterprise
14
+ */
15
+
16
+ // -----------------------------------------------------------------------------
17
+ // Requirements
18
+ // -----------------------------------------------------------------------------
19
+
20
+ var urlPath = require('../util/url-path'),
21
+ /* eslint-disable no-unused-vars*/
22
+ Promise = require('bluebird'),
23
+ /* eslint-enable no-unused-vars*/
24
+ errors = require('../util/errors'),
25
+ httpStatusCodes = require('http-status');
26
+
27
+ // -----------------------------------------------------------------------------
28
+ // Private
29
+ // -----------------------------------------------------------------------------
30
+
31
+ // Base path for all terms of service endpoints
32
+ var BASE_PATH = '/terms_of_services',
33
+ USER_STATUSES_PATH = '/terms_of_service_user_statuses';
34
+
35
+ // ------------------------------------------------------------------------------
36
+ // Public
37
+ // ------------------------------------------------------------------------------
38
+
39
+ /**
40
+ * Simple manager for interacting with all 'Terms of Services' and 'Terms of Service User Statuses' endpoints and actions.
41
+ *
42
+ * @param {BoxClient} client The Box API Client that is responsible for making calls to the API
43
+ * @constructor
44
+ */
45
+ function TermsOfService(client) {
46
+ // Attach the client, for making API calls
47
+ this.client = client;
48
+ }
49
+
50
+ /**
51
+ * Enum value of scope of the custom terms of services set to either managed by an enterprise or enternal to an enterprise
52
+ *
53
+ * @readonly
54
+ * @enum {TermsOfServicesType}
55
+ */
56
+ TermsOfService.prototype.type = {
57
+ MANAGED: 'managed',
58
+ EXTERNAL: 'external'
59
+ };
60
+
61
+ /**
62
+ * Enum value of status of the custom terms of services, either currently enabled or currently disabled
63
+ *
64
+ * @readonly
65
+ * @enum {TermsOfServicesStatus}
66
+ */
67
+ TermsOfService.prototype.status = {
68
+ ENABLED: 'enabled',
69
+ DISABLED: 'disabled'
70
+ };
71
+
72
+ /**
73
+ * Creates a custom terms of services with user specified values
74
+ *
75
+ * API Endpoint: '/terms_of_services'
76
+ * Method: POST
77
+ *
78
+ * @param {TermsOfServicesType} termsOfServicesType - Determine if the custom terms of service is scoped internall or externally to an enterprise
79
+ * @param {TermsOfServicesStatus} termsOfServicesStatus - Determine if the custom terms of service is enabled or disabled
80
+ * @param {string} termsOfServicesText - Text field for message associated with custom terms of services
81
+ * @param {Function} [callback] - Passed the terms of services information if successful, error otherwise
82
+ * @returns {Promise<Object>} A promise resolving to the terms of services object
83
+ */
84
+ TermsOfService.prototype.create = function(termsOfServicesType, termsOfServicesStatus, termsOfServicesText, callback) {
85
+ var params = {
86
+ body: {
87
+ status: termsOfServicesStatus,
88
+ tos_type: termsOfServicesType,
89
+ text: termsOfServicesText
90
+ }
91
+ };
92
+
93
+ var apiPath = urlPath(BASE_PATH);
94
+ return this.client.wrapWithDefaultHandler(this.client.post)(apiPath, params, callback);
95
+ };
96
+
97
+ /**
98
+ * Updates a custom terms of services with new specified values
99
+ *
100
+ * API Endpoint: '/terms_of_services/:termsOfServicesID'
101
+ * Method: PUT
102
+ *
103
+ * @param {string} termsOfServicesID - The id of the custom terms of services to update
104
+ * @param {Object} [options] - Additional options. Can be left null in most cases.
105
+ * @param {TermsOfServicesStatus} [options.status] - Determine if the custom terms of service is scoped internall or externally to an enterprise
106
+ * @param {string} [options.text] - Text field for message associated with custom terms of services
107
+ * @param {Function} [callback] - Passed the terms of services updated information if successful, error otherwise
108
+ * @returns {Promise<Object>} A promise resolving to the terms of services object
109
+ */
110
+ TermsOfService.prototype.update = function(termsOfServicesID, options, callback) {
111
+ var params = {
112
+ body: options
113
+ };
114
+
115
+ var apiPath = urlPath(BASE_PATH, termsOfServicesID);
116
+ return this.client.wrapWithDefaultHandler(this.client.put)(apiPath, params, callback);
117
+ };
118
+
119
+ /**
120
+ * Gets a specific custom terms of services with specified ID
121
+ *
122
+ * API Endpoint: '/terms_of_services/:termsOfServicesID'
123
+ * Method: GET
124
+ *
125
+ * @param {string} termsOfServicesID - The id of the custom terms of services to retrieve
126
+ * @param {Object} [options] - Additional options. Can be left null in most cases.
127
+ * @param {string} [options.fields] - Comma-separated list of fields to return on the collaboration objects
128
+ * @param {Function} [callback] - Passed the terms of services information with specified ID if successful, error otherwise
129
+ * @returns {Promise<Object>} A promise resolving to the terms of services object
130
+ */
131
+ TermsOfService.prototype.get = function(termsOfServicesID, options, callback) {
132
+ var params = {
133
+ qs: options
134
+ };
135
+
136
+ var apiPath = urlPath(BASE_PATH, termsOfServicesID);
137
+ return this.client.wrapWithDefaultHandler(this.client.get)(apiPath, params, callback);
138
+ };
139
+
140
+ /**
141
+ * Gets custom terms of services for the user's enterprise
142
+ *
143
+ * API Endpoint: '/terms_of_services'
144
+ * Method: GET
145
+ *
146
+ * @param {Object} [options] - Additional options. Can be left null in most cases.
147
+ * @param {TermsOfServiceType} [options.tos_type] - Optional, indicates whether the terms of service is set for external or managed under enterprise
148
+ * @param {string} [options.fields] - Comma-separated list of fields to return on the collaboration objects
149
+ * @param {Function} [callback] - Passed the terms of services information if successful, error otherwise
150
+ * @returns {Promise<Object>} A promise resolving to the terms of services object
151
+ */
152
+ TermsOfService.prototype.getAll = function(options, callback) {
153
+ var params = {
154
+ qs: options
155
+ };
156
+
157
+ var apiPath = urlPath(BASE_PATH);
158
+ return this.client.wrapWithDefaultHandler(this.client.get)(apiPath, params, callback);
159
+ };
160
+
161
+ /**
162
+ * Accepts/rejects custom terms of services for the user
163
+ *
164
+ * API Endpoint: '/terms_of_service_user_statuses'
165
+ * Method: POST
166
+ *
167
+ * @param {string} termsOfServicesID - Terms of services ID to retrieve user statuses on
168
+ * @param {bool} isAccepted - Determines wehether the terms of services has been accepted or rejected
169
+ * @param {Object} [options] - Additional options. Can be left null in most cases.
170
+ * @param {string} [options.user_id] - Optional, user id to retrieve terms of service status on, default is current user
171
+ * @param {Function} [callback] - Passed the terms of service user status information if successful, error otherwise
172
+ * @returns {Promise<Object>} A promise resolving to the terms of service user status
173
+ */
174
+ TermsOfService.prototype.createUserStatus = function(termsOfServicesID, isAccepted, options, callback) {
175
+ var params = {
176
+ body: {
177
+ tos: {
178
+ id: termsOfServicesID,
179
+ type: 'terms_of_service'
180
+ },
181
+ is_accepted: isAccepted
182
+ }
183
+ };
184
+
185
+ if (options && options.user_id) {
186
+ params.body.user = {id: options.user_id, type: 'user'};
187
+ }
188
+
189
+ var apiPath = urlPath(USER_STATUSES_PATH);
190
+ return this.client.wrapWithDefaultHandler(this.client.post)(apiPath, params, callback);
191
+ };
192
+
193
+ /**
194
+ * Gets a terms os service status given the terms of services id
195
+ *
196
+ * API Endpoint: '/terms_of_service_user_statuses'
197
+ * Method: GET
198
+ *
199
+ * @param {string} termsOfServicesID - The ID of the terms of services to retrieve status on
200
+ * @param {Object} [options] - Additional options. Can be left null in most cases
201
+ * @param {string} [options.user_id] - Optional, the id of the user to retrieve status of custom terms and service on
202
+ * @param {Function} [callback] - Passed the terms of service user status information if successful, error otherwise
203
+ * @returns {Promise<Object>} A promise resolving to the terms of service user status
204
+ */
205
+ TermsOfService.prototype.getUserStatus = function(termsOfServicesID, options, callback) {
206
+ var params = {
207
+ qs: {
208
+ tos_id: termsOfServicesID
209
+ }
210
+ };
211
+
212
+ if (options) {
213
+ Object.assign(params.qs, options);
214
+ }
215
+
216
+ var apiPath = urlPath(USER_STATUSES_PATH);
217
+ return this.client.get(apiPath, params)
218
+ .then(response => {
219
+ if (response.statusCode !== 200) {
220
+ throw errors.buildUnexpectedResponseError(response);
221
+ }
222
+ return response.body.entries[0];
223
+ })
224
+ .asCallback(callback);
225
+ };
226
+
227
+ /**
228
+ * Accepts/rejects custom terms of services for the user
229
+ *
230
+ * API Endpoint: '/terms_of_service_user_statuses'
231
+ * Method: PUT
232
+ *
233
+ * @param {string} termsOfServiceUserStatusID - Terms of service user status object ID
234
+ * @param {bool} isAccepted - Determines wehether the terms of services has been accepted or rejected
235
+ * @param {Function} [callback] - Passed the terms of service user status updated information if successful, error otherwise
236
+ * @returns {Promise<Object>} A promise resolving to the updated terms of service user status
237
+ */
238
+ TermsOfService.prototype.updateUserStatus = function(termsOfServiceUserStatusID, isAccepted, callback) {
239
+ var params = {
240
+ body: {
241
+ is_accepted: isAccepted
242
+ }
243
+ };
244
+
245
+ var apiPath = urlPath(USER_STATUSES_PATH, termsOfServiceUserStatusID);
246
+ return this.client.wrapWithDefaultHandler(this.client.put)(apiPath, params, callback);
247
+ };
248
+
249
+ /**
250
+ * Creates a user status for terms of service, if already exists then update existing user status for terms of service
251
+ *
252
+ * API Endpoint: '/terms_of_service_user_statuses'
253
+ * Method: POST/PUT
254
+ *
255
+ * @param {string} termsOfServicesID - Terms of services ID to retrieve user statuses on
256
+ * @param {bool} isAccepted - Determines wehether the terms of services has been accepted or rejected
257
+ * @param {Object} [options] - Additional options. Can be left null in most cases.
258
+ * @param {string} [options.user_id] - Optional, user id to retrieve terms of service status on, default is current user
259
+ * @param {Function} [callback] - Passed the terms of service user status information if successful, error otherwise
260
+ * @returns {Promise<Object>} A promise resolving to the terms of service user status
261
+ */
262
+ TermsOfService.prototype.setUserStatus = function(termsOfServicesID, isAccepted, options, callback) {
263
+ var params = {
264
+ body: {
265
+ tos: {
266
+ id: termsOfServicesID,
267
+ type: 'terms_of_service'
268
+ },
269
+ is_accepted: isAccepted
270
+ }
271
+ };
272
+
273
+ if (options && options.user_id) {
274
+ params.body.user = {id: options.user_id, type: 'user'};
275
+ }
276
+
277
+ var apiPath = urlPath(USER_STATUSES_PATH);
278
+
279
+ return this.client.post(apiPath, params)
280
+ .then(response => {
281
+ switch (response.statusCode) {
282
+
283
+ // 200 - A user status has been successfully created on terms of service
284
+ // return the terms of service user status object
285
+ case httpStatusCodes.OK:
286
+ return response.body;
287
+
288
+ // 409 - Conflict
289
+ // Terms of Service already exists. Update the existing terms of service object
290
+ case httpStatusCodes.CONFLICT:
291
+ var getOptions = Object.assign({fields: 'id'}, options);
292
+ return this.getUserStatus(termsOfServicesID, getOptions)
293
+ .then(userStatus => this.updateUserStatus(userStatus.id, isAccepted));
294
+
295
+ default:
296
+ throw errors.buildUnexpectedResponseError(response);
297
+ }
298
+ })
299
+ .asCallback(callback);
300
+ };
301
+
302
+ /**
303
+ * @module box-node-sdk/lib/managers/terms-of-service
304
+ * @see {@Link TermsOfService}
305
+ */
306
+ module.exports = TermsOfService;
307
+
@@ -116,7 +116,9 @@ AppAuthSession.prototype.revokeTokens = function(options) {
116
116
  * Exchange the client access token for one with lower scope
117
117
  * @param {string|string[]} scopes The scope(s) requested for the new token
118
118
  * @param {string} [resource] The absolute URL of an API resource to scope the new token to
119
- * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant
119
+ * @param {Object} [options] - Optional parameters
120
+ * @param {TokenRequestOptions} [options.tokenRequestOptions] - Sets optional behavior for the token grant
121
+ * @param {ActorParams} [options.actor] - Optional actor parameters for creating annotator tokens
120
122
  * @returns {Promise<TokenInfo>} Promise resolving to the new token info
121
123
  */
122
124
  AppAuthSession.prototype.exchangeToken = function(scopes, resource, options) {
@@ -57,7 +57,9 @@ BasicSession.prototype.revokeTokens = function(options) {
57
57
  * Exchange the client access token for one with lower scope
58
58
  * @param {string|string[]} scopes The scope(s) requested for the new token
59
59
  * @param {string} [resource] The absolute URL of an API resource to scope the new token to
60
- * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant
60
+ * @param {Object} [options] - Optional parameters
61
+ * @param {TokenRequestOptions} [options.tokenRequestOptions] - Sets optional behavior for the token grant
62
+ * @param {ActorParams} [options.actor] - Optional actor parameters for creating annotator tokens
61
63
  * @returns {Promise<TokenInfo>} Promise resolving to the new token info
62
64
  */
63
65
  BasicSession.prototype.exchangeToken = function(scopes, resource, options) {
@@ -217,7 +217,8 @@ PersistentSession.prototype.revokeTokens = function(options) {
217
217
  * Exchange the client access token for one with lower scope
218
218
  * @param {string|string[]} scopes The scope(s) requested for the new token
219
219
  * @param {string} [resource] The absolute URL of an API resource to scope the new token to
220
- * @param {TokenRequestOptions} [options] - Sets optional behavior for the token grant
220
+ * @param {Object} [options] - Optional parameters
221
+ * @param {TokenRequestOptions} [options.tokenRequestOptions] - Sets optional behavior for the token grant
221
222
  * @returns {void}
222
223
  */
223
224
  PersistentSession.prototype.exchangeToken = function(scopes, resource, options) {