acl.js 26 KB

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