1 | // Copyright 2019 Google LLC
|
2 | //
|
3 | // Licensed under the Apache License, Version 2.0 (the "License");
|
4 | // you may not use this file except in compliance with the License.
|
5 | // You may obtain a copy of the License at
|
6 | //
|
7 | // http://www.apache.org/licenses/LICENSE-2.0
|
8 | //
|
9 | // Unless required by applicable law or agreed to in writing, software
|
10 | // distributed under the License is distributed on an "AS IS" BASIS,
|
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 | // See the License for the specific language governing permissions and
|
13 | // limitations under the License.
|
14 | import { promisifyAll } from '@google-cloud/promisify';
|
15 | /**
|
16 | * Attach functionality to a {@link Storage.acl} instance. This will add an
|
17 | * object for each role group (owners, readers, and writers), with each object
|
18 | * containing methods to add or delete a type of entity.
|
19 | *
|
20 | * As an example, here are a few methods that are created.
|
21 | *
|
22 | * myBucket.acl.readers.deleteGroup('groupId', function(err) {});
|
23 | *
|
24 | * myBucket.acl.owners.addUser('email@example.com', function(err, acl) {});
|
25 | *
|
26 | * myBucket.acl.writers.addDomain('example.com', function(err, acl) {});
|
27 | *
|
28 | * @private
|
29 | */
|
30 | class AclRoleAccessorMethods {
|
31 | constructor() {
|
32 | this.owners = {};
|
33 | this.readers = {};
|
34 | this.writers = {};
|
35 | /**
|
36 | * An object of convenience methods to add or delete owner ACL permissions
|
37 | * for a given entity.
|
38 | *
|
39 | * The supported methods include:
|
40 | *
|
41 | * - `myFile.acl.owners.addAllAuthenticatedUsers`
|
42 | * - `myFile.acl.owners.deleteAllAuthenticatedUsers`
|
43 | * - `myFile.acl.owners.addAllUsers`
|
44 | * - `myFile.acl.owners.deleteAllUsers`
|
45 | * - `myFile.acl.owners.addDomain`
|
46 | * - `myFile.acl.owners.deleteDomain`
|
47 | * - `myFile.acl.owners.addGroup`
|
48 | * - `myFile.acl.owners.deleteGroup`
|
49 | * - `myFile.acl.owners.addProject`
|
50 | * - `myFile.acl.owners.deleteProject`
|
51 | * - `myFile.acl.owners.addUser`
|
52 | * - `myFile.acl.owners.deleteUser`
|
53 | *
|
54 | * @name Acl#owners
|
55 | *
|
56 | * @example
|
57 | * ```
|
58 | * const storage = require('@google-cloud/storage')();
|
59 | * const myBucket = storage.bucket('my-bucket');
|
60 | * const myFile = myBucket.file('my-file');
|
61 | *
|
62 | * //-
|
63 | * // Add a user as an owner of a file.
|
64 | * //-
|
65 | * const myBucket = gcs.bucket('my-bucket');
|
66 | * const myFile = myBucket.file('my-file');
|
67 | * myFile.acl.owners.addUser('email@example.com', function(err, aclObject)
|
68 | * {});
|
69 | *
|
70 | * //-
|
71 | * // For reference, the above command is the same as running the following.
|
72 | * //-
|
73 | * myFile.acl.add({
|
74 | * entity: 'user-email@example.com',
|
75 | * role: gcs.acl.OWNER_ROLE
|
76 | * }, function(err, aclObject) {});
|
77 | *
|
78 | * //-
|
79 | * // If the callback is omitted, we'll return a Promise.
|
80 | * //-
|
81 | * myFile.acl.owners.addUser('email@example.com').then(function(data) {
|
82 | * const aclObject = data[0];
|
83 | * const apiResponse = data[1];
|
84 | * });
|
85 | * ```
|
86 | */
|
87 | this.owners = {};
|
88 | /**
|
89 | * An object of convenience methods to add or delete reader ACL permissions
|
90 | * for a given entity.
|
91 | *
|
92 | * The supported methods include:
|
93 | *
|
94 | * - `myFile.acl.readers.addAllAuthenticatedUsers`
|
95 | * - `myFile.acl.readers.deleteAllAuthenticatedUsers`
|
96 | * - `myFile.acl.readers.addAllUsers`
|
97 | * - `myFile.acl.readers.deleteAllUsers`
|
98 | * - `myFile.acl.readers.addDomain`
|
99 | * - `myFile.acl.readers.deleteDomain`
|
100 | * - `myFile.acl.readers.addGroup`
|
101 | * - `myFile.acl.readers.deleteGroup`
|
102 | * - `myFile.acl.readers.addProject`
|
103 | * - `myFile.acl.readers.deleteProject`
|
104 | * - `myFile.acl.readers.addUser`
|
105 | * - `myFile.acl.readers.deleteUser`
|
106 | *
|
107 | * @name Acl#readers
|
108 | *
|
109 | * @example
|
110 | * ```
|
111 | * const storage = require('@google-cloud/storage')();
|
112 | * const myBucket = storage.bucket('my-bucket');
|
113 | * const myFile = myBucket.file('my-file');
|
114 | *
|
115 | * //-
|
116 | * // Add a user as a reader of a file.
|
117 | * //-
|
118 | * myFile.acl.readers.addUser('email@example.com', function(err, aclObject)
|
119 | * {});
|
120 | *
|
121 | * //-
|
122 | * // For reference, the above command is the same as running the following.
|
123 | * //-
|
124 | * myFile.acl.add({
|
125 | * entity: 'user-email@example.com',
|
126 | * role: gcs.acl.READER_ROLE
|
127 | * }, function(err, aclObject) {});
|
128 | *
|
129 | * //-
|
130 | * // If the callback is omitted, we'll return a Promise.
|
131 | * //-
|
132 | * myFile.acl.readers.addUser('email@example.com').then(function(data) {
|
133 | * const aclObject = data[0];
|
134 | * const apiResponse = data[1];
|
135 | * });
|
136 | * ```
|
137 | */
|
138 | this.readers = {};
|
139 | /**
|
140 | * An object of convenience methods to add or delete writer ACL permissions
|
141 | * for a given entity.
|
142 | *
|
143 | * The supported methods include:
|
144 | *
|
145 | * - `myFile.acl.writers.addAllAuthenticatedUsers`
|
146 | * - `myFile.acl.writers.deleteAllAuthenticatedUsers`
|
147 | * - `myFile.acl.writers.addAllUsers`
|
148 | * - `myFile.acl.writers.deleteAllUsers`
|
149 | * - `myFile.acl.writers.addDomain`
|
150 | * - `myFile.acl.writers.deleteDomain`
|
151 | * - `myFile.acl.writers.addGroup`
|
152 | * - `myFile.acl.writers.deleteGroup`
|
153 | * - `myFile.acl.writers.addProject`
|
154 | * - `myFile.acl.writers.deleteProject`
|
155 | * - `myFile.acl.writers.addUser`
|
156 | * - `myFile.acl.writers.deleteUser`
|
157 | *
|
158 | * @name Acl#writers
|
159 | *
|
160 | * @example
|
161 | * ```
|
162 | * const storage = require('@google-cloud/storage')();
|
163 | * const myBucket = storage.bucket('my-bucket');
|
164 | * const myFile = myBucket.file('my-file');
|
165 | *
|
166 | * //-
|
167 | * // Add a user as a writer of a file.
|
168 | * //-
|
169 | * myFile.acl.writers.addUser('email@example.com', function(err, aclObject)
|
170 | * {});
|
171 | *
|
172 | * //-
|
173 | * // For reference, the above command is the same as running the following.
|
174 | * //-
|
175 | * myFile.acl.add({
|
176 | * entity: 'user-email@example.com',
|
177 | * role: gcs.acl.WRITER_ROLE
|
178 | * }, function(err, aclObject) {});
|
179 | *
|
180 | * //-
|
181 | * // If the callback is omitted, we'll return a Promise.
|
182 | * //-
|
183 | * myFile.acl.writers.addUser('email@example.com').then(function(data) {
|
184 | * const aclObject = data[0];
|
185 | * const apiResponse = data[1];
|
186 | * });
|
187 | * ```
|
188 | */
|
189 | this.writers = {};
|
190 | AclRoleAccessorMethods.roles.forEach(this._assignAccessMethods.bind(this));
|
191 | }
|
192 | _assignAccessMethods(role) {
|
193 | const accessMethods = AclRoleAccessorMethods.accessMethods;
|
194 | const entities = AclRoleAccessorMethods.entities;
|
195 | const roleGroup = role.toLowerCase() + 's';
|
196 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
197 | this[roleGroup] = entities.reduce((acc, entity) => {
|
198 | const isPrefix = entity.charAt(entity.length - 1) === '-';
|
199 | accessMethods.forEach(accessMethod => {
|
200 | let method = accessMethod + entity[0].toUpperCase() + entity.substring(1);
|
201 | if (isPrefix) {
|
202 | method = method.replace('-', '');
|
203 | }
|
204 | // Wrap the parent accessor method (e.g. `add` or `delete`) to avoid the
|
205 | // more complex API of specifying an `entity` and `role`.
|
206 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
207 | acc[method] = (entityId, options, callback) => {
|
208 | let apiEntity;
|
209 | if (typeof options === 'function') {
|
210 | callback = options;
|
211 | options = {};
|
212 | }
|
213 | if (isPrefix) {
|
214 | apiEntity = entity + entityId;
|
215 | }
|
216 | else {
|
217 | // If the entity is not a prefix, it is a special entity group
|
218 | // that does not require further details. The accessor methods
|
219 | // only accept a callback.
|
220 | apiEntity = entity;
|
221 | callback = entityId;
|
222 | }
|
223 | options = Object.assign({
|
224 | entity: apiEntity,
|
225 | role,
|
226 | }, options);
|
227 | const args = [options];
|
228 | if (typeof callback === 'function') {
|
229 | args.push(callback);
|
230 | }
|
231 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
232 | return this[accessMethod].apply(this, args);
|
233 | };
|
234 | });
|
235 | return acc;
|
236 | }, {});
|
237 | }
|
238 | }
|
239 | AclRoleAccessorMethods.accessMethods = ['add', 'delete'];
|
240 | AclRoleAccessorMethods.entities = [
|
241 | // Special entity groups that do not require further specification.
|
242 | 'allAuthenticatedUsers',
|
243 | 'allUsers',
|
244 | // Entity groups that require specification, e.g. `user-email@example.com`.
|
245 | 'domain-',
|
246 | 'group-',
|
247 | 'project-',
|
248 | 'user-',
|
249 | ];
|
250 | AclRoleAccessorMethods.roles = ['OWNER', 'READER', 'WRITER'];
|
251 | /**
|
252 | * Cloud Storage uses access control lists (ACLs) to manage object and
|
253 | * bucket access. ACLs are the mechanism you use to share objects with other
|
254 | * users and allow other users to access your buckets and objects.
|
255 | *
|
256 | * An ACL consists of one or more entries, where each entry grants permissions
|
257 | * to an entity. Permissions define the actions that can be performed against an
|
258 | * object or bucket (for example, `READ` or `WRITE`); the entity defines who the
|
259 | * permission applies to (for example, a specific user or group of users).
|
260 | *
|
261 | * Where an `entity` value is accepted, we follow the format the Cloud Storage
|
262 | * API expects.
|
263 | *
|
264 | * Refer to
|
265 | * https://cloud.google.com/storage/docs/json_api/v1/defaultObjectAccessControls
|
266 | * for the most up-to-date values.
|
267 | *
|
268 | * - `user-userId`
|
269 | * - `user-email`
|
270 | * - `group-groupId`
|
271 | * - `group-email`
|
272 | * - `domain-domain`
|
273 | * - `project-team-projectId`
|
274 | * - `allUsers`
|
275 | * - `allAuthenticatedUsers`
|
276 | *
|
277 | * Examples:
|
278 | *
|
279 | * - The user "liz@example.com" would be `user-liz@example.com`.
|
280 | * - The group "example@googlegroups.com" would be
|
281 | * `group-example@googlegroups.com`.
|
282 | * - To refer to all members of the Google Apps for Business domain
|
283 | * "example.com", the entity would be `domain-example.com`.
|
284 | *
|
285 | * For more detailed information, see
|
286 | * {@link http://goo.gl/6qBBPO| About Access Control Lists}.
|
287 | *
|
288 | * @constructor Acl
|
289 | * @mixin
|
290 | * @param {object} options Configuration options.
|
291 | */
|
292 | class Acl extends AclRoleAccessorMethods {
|
293 | constructor(options) {
|
294 | super();
|
295 | this.pathPrefix = options.pathPrefix;
|
296 | this.request_ = options.request;
|
297 | }
|
298 | /**
|
299 | * @typedef {array} AddAclResponse
|
300 | * @property {object} 0 The Acl Objects.
|
301 | * @property {object} 1 The full API response.
|
302 | */
|
303 | /**
|
304 | * @callback AddAclCallback
|
305 | * @param {?Error} err Request error, if any.
|
306 | * @param {object} acl The Acl Objects.
|
307 | * @param {object} apiResponse The full API response.
|
308 | */
|
309 | /**
|
310 | * Add access controls on a {@link Bucket} or {@link File}.
|
311 | *
|
312 | * See {@link https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls/insert| BucketAccessControls: insert API Documentation}
|
313 | * See {@link https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls/insert| ObjectAccessControls: insert API Documentation}
|
314 | *
|
315 | * @param {object} options Configuration options.
|
316 | * @param {string} options.entity Whose permissions will be added.
|
317 | * @param {string} options.role Permissions allowed for the defined entity.
|
318 | * See {@link https://cloud.google.com/storage/docs/access-control Access
|
319 | * Control}.
|
320 | * @param {number} [options.generation] **File Objects Only** Select a specific
|
321 | * revision of this file (as opposed to the latest version, the default).
|
322 | * @param {string} [options.userProject] The ID of the project which will be
|
323 | * billed for the request.
|
324 | * @param {AddAclCallback} [callback] Callback function.
|
325 | * @returns {Promise<AddAclResponse>}
|
326 | *
|
327 | * @example
|
328 | * ```
|
329 | * const storage = require('@google-cloud/storage')();
|
330 | * const myBucket = storage.bucket('my-bucket');
|
331 | * const myFile = myBucket.file('my-file');
|
332 | *
|
333 | * const options = {
|
334 | * entity: 'user-useremail@example.com',
|
335 | * role: gcs.acl.OWNER_ROLE
|
336 | * };
|
337 | *
|
338 | * myBucket.acl.add(options, function(err, aclObject, apiResponse) {});
|
339 | *
|
340 | * //-
|
341 | * // For file ACL operations, you can also specify a `generation` property.
|
342 | * // Here is how you would grant ownership permissions to a user on a
|
343 | * specific
|
344 | * // revision of a file.
|
345 | * //-
|
346 | * myFile.acl.add({
|
347 | * entity: 'user-useremail@example.com',
|
348 | * role: gcs.acl.OWNER_ROLE,
|
349 | * generation: 1
|
350 | * }, function(err, aclObject, apiResponse) {});
|
351 | *
|
352 | * //-
|
353 | * // If the callback is omitted, we'll return a Promise.
|
354 | * //-
|
355 | * myBucket.acl.add(options).then(function(data) {
|
356 | * const aclObject = data[0];
|
357 | * const apiResponse = data[1];
|
358 | * });
|
359 | *
|
360 | * ```
|
361 | * @example <caption>include:samples/acl.js</caption>
|
362 | * region_tag:storage_add_file_owner
|
363 | * Example of adding an owner to a file:
|
364 | *
|
365 | * @example <caption>include:samples/acl.js</caption>
|
366 | * region_tag:storage_add_bucket_owner
|
367 | * Example of adding an owner to a bucket:
|
368 | *
|
369 | * @example <caption>include:samples/acl.js</caption>
|
370 | * region_tag:storage_add_bucket_default_owner
|
371 | * Example of adding a default owner to a bucket:
|
372 | */
|
373 | add(options, callback) {
|
374 | const query = {};
|
375 | if (options.generation) {
|
376 | query.generation = options.generation;
|
377 | }
|
378 | if (options.userProject) {
|
379 | query.userProject = options.userProject;
|
380 | }
|
381 | this.request({
|
382 | method: 'POST',
|
383 | uri: '',
|
384 | qs: query,
|
385 | maxRetries: 0, //explicitly set this value since this is a non-idempotent function
|
386 | json: {
|
387 | entity: options.entity,
|
388 | role: options.role.toUpperCase(),
|
389 | },
|
390 | }, (err, resp) => {
|
391 | if (err) {
|
392 | callback(err, null, resp);
|
393 | return;
|
394 | }
|
395 | callback(null, this.makeAclObject_(resp), resp);
|
396 | });
|
397 | }
|
398 | /**
|
399 | * @typedef {array} RemoveAclResponse
|
400 | * @property {object} 0 The full API response.
|
401 | */
|
402 | /**
|
403 | * @callback RemoveAclCallback
|
404 | * @param {?Error} err Request error, if any.
|
405 | * @param {object} apiResponse The full API response.
|
406 | */
|
407 | /**
|
408 | * Delete access controls on a {@link Bucket} or {@link File}.
|
409 | *
|
410 | * See {@link https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls/delete| BucketAccessControls: delete API Documentation}
|
411 | * See {@link https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls/delete| ObjectAccessControls: delete API Documentation}
|
412 | *
|
413 | * @param {object} options Configuration object.
|
414 | * @param {string} options.entity Whose permissions will be revoked.
|
415 | * @param {int} [options.generation] **File Objects Only** Select a specific
|
416 | * revision of this file (as opposed to the latest version, the default).
|
417 | * @param {string} [options.userProject] The ID of the project which will be
|
418 | * billed for the request.
|
419 | * @param {RemoveAclCallback} callback The callback function.
|
420 | * @returns {Promise<RemoveAclResponse>}
|
421 | *
|
422 | * @example
|
423 | * ```
|
424 | * const storage = require('@google-cloud/storage')();
|
425 | * const myBucket = storage.bucket('my-bucket');
|
426 | * const myFile = myBucket.file('my-file');
|
427 | *
|
428 | * myBucket.acl.delete({
|
429 | * entity: 'user-useremail@example.com'
|
430 | * }, function(err, apiResponse) {});
|
431 | *
|
432 | * //-
|
433 | * // For file ACL operations, you can also specify a `generation` property.
|
434 | * //-
|
435 | * myFile.acl.delete({
|
436 | * entity: 'user-useremail@example.com',
|
437 | * generation: 1
|
438 | * }, function(err, apiResponse) {});
|
439 | *
|
440 | * //-
|
441 | * // If the callback is omitted, we'll return a Promise.
|
442 | * //-
|
443 | * myFile.acl.delete().then(function(data) {
|
444 | * const apiResponse = data[0];
|
445 | * });
|
446 | *
|
447 | * ```
|
448 | * @example <caption>include:samples/acl.js</caption>
|
449 | * region_tag:storage_remove_bucket_owner
|
450 | * Example of removing an owner from a bucket:
|
451 | *
|
452 | * @example <caption>include:samples/acl.js</caption>
|
453 | * region_tag:storage_remove_bucket_default_owner
|
454 | * Example of removing a default owner from a bucket:
|
455 | *
|
456 | * @example <caption>include:samples/acl.js</caption>
|
457 | * region_tag:storage_remove_file_owner
|
458 | * Example of removing an owner from a bucket:
|
459 | */
|
460 | delete(options, callback) {
|
461 | const query = {};
|
462 | if (options.generation) {
|
463 | query.generation = options.generation;
|
464 | }
|
465 | if (options.userProject) {
|
466 | query.userProject = options.userProject;
|
467 | }
|
468 | this.request({
|
469 | method: 'DELETE',
|
470 | uri: '/' + encodeURIComponent(options.entity),
|
471 | qs: query,
|
472 | }, (err, resp) => {
|
473 | callback(err, resp);
|
474 | });
|
475 | }
|
476 | /**
|
477 | * @typedef {array} GetAclResponse
|
478 | * @property {object|object[]} 0 Single or array of Acl Objects.
|
479 | * @property {object} 1 The full API response.
|
480 | */
|
481 | /**
|
482 | * @callback GetAclCallback
|
483 | * @param {?Error} err Request error, if any.
|
484 | * @param {object|object[]} acl Single or array of Acl Objects.
|
485 | * @param {object} apiResponse The full API response.
|
486 | */
|
487 | /**
|
488 | * Get access controls on a {@link Bucket} or {@link File}. If
|
489 | * an entity is omitted, you will receive an array of all applicable access
|
490 | * controls.
|
491 | *
|
492 | * See {@link https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls/get| BucketAccessControls: get API Documentation}
|
493 | * See {@link https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls/get| ObjectAccessControls: get API Documentation}
|
494 | *
|
495 | * @param {object|function} [options] Configuration options. If you want to
|
496 | * receive a list of all access controls, pass the callback function as
|
497 | * the only argument.
|
498 | * @param {string} options.entity Whose permissions will be fetched.
|
499 | * @param {number} [options.generation] **File Objects Only** Select a specific
|
500 | * revision of this file (as opposed to the latest version, the default).
|
501 | * @param {string} [options.userProject] The ID of the project which will be
|
502 | * billed for the request.
|
503 | * @param {GetAclCallback} [callback] Callback function.
|
504 | * @returns {Promise<GetAclResponse>}
|
505 | *
|
506 | * @example
|
507 | * ```
|
508 | * const storage = require('@google-cloud/storage')();
|
509 | * const myBucket = storage.bucket('my-bucket');
|
510 | * const myFile = myBucket.file('my-file');
|
511 | *
|
512 | * myBucket.acl.get({
|
513 | * entity: 'user-useremail@example.com'
|
514 | * }, function(err, aclObject, apiResponse) {});
|
515 | *
|
516 | * //-
|
517 | * // Get all access controls.
|
518 | * //-
|
519 | * myBucket.acl.get(function(err, aclObjects, apiResponse) {
|
520 | * // aclObjects = [
|
521 | * // {
|
522 | * // entity: 'user-useremail@example.com',
|
523 | * // role: 'owner'
|
524 | * // }
|
525 | * // ]
|
526 | * });
|
527 | *
|
528 | * //-
|
529 | * // For file ACL operations, you can also specify a `generation` property.
|
530 | * //-
|
531 | * myFile.acl.get({
|
532 | * entity: 'user-useremail@example.com',
|
533 | * generation: 1
|
534 | * }, function(err, aclObject, apiResponse) {});
|
535 | *
|
536 | * //-
|
537 | * // If the callback is omitted, we'll return a Promise.
|
538 | * //-
|
539 | * myBucket.acl.get().then(function(data) {
|
540 | * const aclObject = data[0];
|
541 | * const apiResponse = data[1];
|
542 | * });
|
543 | *
|
544 | * ```
|
545 | * @example <caption>include:samples/acl.js</caption>
|
546 | * region_tag:storage_print_file_acl
|
547 | * Example of printing a file's ACL:
|
548 | *
|
549 | * @example <caption>include:samples/acl.js</caption>
|
550 | * region_tag:storage_print_file_acl_for_user
|
551 | * Example of printing a file's ACL for a specific user:
|
552 | *
|
553 | * @example <caption>include:samples/acl.js</caption>
|
554 | * region_tag:storage_print_bucket_acl
|
555 | * Example of printing a bucket's ACL:
|
556 | *
|
557 | * @example <caption>include:samples/acl.js</caption>
|
558 | * region_tag:storage_print_bucket_acl_for_user
|
559 | * Example of printing a bucket's ACL for a specific user:
|
560 | */
|
561 | get(optionsOrCallback, cb) {
|
562 | const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : null;
|
563 | const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb;
|
564 | let path = '';
|
565 | const query = {};
|
566 | if (options) {
|
567 | path = '/' + encodeURIComponent(options.entity);
|
568 | if (options.generation) {
|
569 | query.generation = options.generation;
|
570 | }
|
571 | if (options.userProject) {
|
572 | query.userProject = options.userProject;
|
573 | }
|
574 | }
|
575 | this.request({
|
576 | uri: path,
|
577 | qs: query,
|
578 | }, (err, resp) => {
|
579 | if (err) {
|
580 | callback(err, null, resp);
|
581 | return;
|
582 | }
|
583 | let results;
|
584 | if (resp.items) {
|
585 | results = resp.items.map(this.makeAclObject_);
|
586 | }
|
587 | else {
|
588 | results = this.makeAclObject_(resp);
|
589 | }
|
590 | callback(null, results, resp);
|
591 | });
|
592 | }
|
593 | /**
|
594 | * @typedef {array} UpdateAclResponse
|
595 | * @property {object} 0 The updated Acl Objects.
|
596 | * @property {object} 1 The full API response.
|
597 | */
|
598 | /**
|
599 | * @callback UpdateAclCallback
|
600 | * @param {?Error} err Request error, if any.
|
601 | * @param {object} acl The updated Acl Objects.
|
602 | * @param {object} apiResponse The full API response.
|
603 | */
|
604 | /**
|
605 | * Update access controls on a {@link Bucket} or {@link File}.
|
606 | *
|
607 | * See {@link https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls/update| BucketAccessControls: update API Documentation}
|
608 | * See {@link https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls/update| ObjectAccessControls: update API Documentation}
|
609 | *
|
610 | * @param {object} options Configuration options.
|
611 | * @param {string} options.entity Whose permissions will be updated.
|
612 | * @param {string} options.role Permissions allowed for the defined entity.
|
613 | * See {@link Storage.acl}.
|
614 | * @param {number} [options.generation] **File Objects Only** Select a specific
|
615 | * revision of this file (as opposed to the latest version, the default).
|
616 | * @param {string} [options.userProject] The ID of the project which will be
|
617 | * billed for the request.
|
618 | * @param {UpdateAclCallback} [callback] Callback function.
|
619 | * @returns {Promise<UpdateAclResponse>}
|
620 | *
|
621 | * @example
|
622 | * ```
|
623 | * const storage = require('@google-cloud/storage')();
|
624 | * const myBucket = storage.bucket('my-bucket');
|
625 | * const myFile = myBucket.file('my-file');
|
626 | *
|
627 | * const options = {
|
628 | * entity: 'user-useremail@example.com',
|
629 | * role: gcs.acl.WRITER_ROLE
|
630 | * };
|
631 | *
|
632 | * myBucket.acl.update(options, function(err, aclObject, apiResponse) {});
|
633 | *
|
634 | * //-
|
635 | * // For file ACL operations, you can also specify a `generation` property.
|
636 | * //-
|
637 | * myFile.acl.update({
|
638 | * entity: 'user-useremail@example.com',
|
639 | * role: gcs.acl.WRITER_ROLE,
|
640 | * generation: 1
|
641 | * }, function(err, aclObject, apiResponse) {});
|
642 | *
|
643 | * //-
|
644 | * // If the callback is omitted, we'll return a Promise.
|
645 | * //-
|
646 | * myFile.acl.update(options).then(function(data) {
|
647 | * const aclObject = data[0];
|
648 | * const apiResponse = data[1];
|
649 | * });
|
650 | * ```
|
651 | */
|
652 | update(options, callback) {
|
653 | const query = {};
|
654 | if (options.generation) {
|
655 | query.generation = options.generation;
|
656 | }
|
657 | if (options.userProject) {
|
658 | query.userProject = options.userProject;
|
659 | }
|
660 | this.request({
|
661 | method: 'PUT',
|
662 | uri: '/' + encodeURIComponent(options.entity),
|
663 | qs: query,
|
664 | json: {
|
665 | role: options.role.toUpperCase(),
|
666 | },
|
667 | }, (err, resp) => {
|
668 | if (err) {
|
669 | callback(err, null, resp);
|
670 | return;
|
671 | }
|
672 | callback(null, this.makeAclObject_(resp), resp);
|
673 | });
|
674 | }
|
675 | /**
|
676 | * Transform API responses to a consistent object format.
|
677 | *
|
678 | * @private
|
679 | */
|
680 | makeAclObject_(accessControlObject) {
|
681 | const obj = {
|
682 | entity: accessControlObject.entity,
|
683 | role: accessControlObject.role,
|
684 | };
|
685 | if (accessControlObject.projectTeam) {
|
686 | obj.projectTeam = accessControlObject.projectTeam;
|
687 | }
|
688 | return obj;
|
689 | }
|
690 | /**
|
691 | * Patch requests up to the bucket's request object.
|
692 | *
|
693 | * @private
|
694 | *
|
695 | * @param {string} method Action.
|
696 | * @param {string} path Request path.
|
697 | * @param {*} query Request query object.
|
698 | * @param {*} body Request body contents.
|
699 | * @param {function} callback Callback function.
|
700 | */
|
701 | request(reqOpts, callback) {
|
702 | reqOpts.uri = this.pathPrefix + reqOpts.uri;
|
703 | this.request_(reqOpts, callback);
|
704 | }
|
705 | }
|
706 | /*! Developer Documentation
|
707 | *
|
708 | * All async methods (except for streams) will return a Promise in the event
|
709 | * that a callback is omitted.
|
710 | */
|
711 | promisifyAll(Acl, {
|
712 | exclude: ['request'],
|
713 | });
|
714 | export { Acl, AclRoleAccessorMethods };
|