Skip to content

Commit c7db475

Browse files
fix: improve the types on acl.ts (#459)
1 parent aef6b5f commit c7db475

3 files changed

Lines changed: 111 additions & 57 deletions

File tree

handwritten/storage/src/acl.ts

Lines changed: 95 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,35 @@ import * as is from 'is';
2323
import {DecorateRequestOptions, BodyResponseCallback} from '@google-cloud/common';
2424
import * as r from 'request';
2525

26+
export interface AclOptions {
27+
pathPrefix: string;
28+
request: typeof r;
29+
}
30+
31+
export type GetAclResponse =
32+
[AccessControlObject | AccessControlObject[], r.Response];
33+
export interface GetAclCallback {
34+
(err: Error|null, acl?: AccessControlObject|AccessControlObject[]|null,
35+
apiResponse?: r.Response): void;
36+
}
37+
export interface GetAclOptions {
38+
entity: string;
39+
generation?: number;
40+
userProject?: string;
41+
}
42+
43+
export interface UpdateAclOptions {
44+
entity: string;
45+
role: string;
46+
generation?: number;
47+
userProject?: string;
48+
}
49+
export type UpdateAclResponse = [AccessControlObject, r.Response];
50+
export interface UpdateAclCallback {
51+
(err: Error|null, acl?: AccessControlObject|null,
52+
apiResponse?: r.Response): void;
53+
}
54+
2655
export interface AddAclOptions {
2756
entity: string;
2857
role: string;
@@ -38,13 +67,18 @@ export type RemoveAclResponse = [r.Response];
3867
export interface RemoveAclCallback {
3968
(err: Error|null, apiResponse?: r.Response): void;
4069
}
70+
export interface RemoveAclOptions {
71+
entity: string;
72+
generation?: number;
73+
userProject?: string;
74+
}
4175

4276
interface AclQuery {
4377
generation: number;
4478
userProject: string;
4579
}
4680

47-
interface AccessControlObject {
81+
export interface AccessControlObject {
4882
entity: string;
4983
role: string;
5084
projectTeam: string;
@@ -243,7 +277,8 @@ class AclRoleAccessorMethods {
243277
const entities = AclRoleAccessorMethods.entities;
244278
const roleGroup = role.toLowerCase() + 's';
245279

246-
this[roleGroup] = entities.reduce((acc, entity) => {
280+
// tslint:disable-next-line:no-any
281+
(this as any)[roleGroup] = entities.reduce((acc, entity) => {
247282
const isPrefix = entity.charAt(entity.length - 1) === '-';
248283

249284
accessMethods.forEach(accessMethod => {
@@ -255,39 +290,42 @@ class AclRoleAccessorMethods {
255290

256291
// Wrap the parent accessor method (e.g. `add` or `delete`) to avoid the
257292
// more complex API of specifying an `entity` and `role`.
258-
acc[method] = (entityId, options, callback) => {
259-
let apiEntity;
260-
261-
if (is.fn(options)) {
262-
callback = options;
263-
options = {};
264-
}
265-
266-
if (isPrefix) {
267-
apiEntity = entity + entityId;
268-
} else {
269-
// If the entity is not a prefix, it is a special entity group that
270-
// does not require further details. The accessor methods only
271-
// accept a callback.
272-
apiEntity = entity;
273-
callback = entityId;
274-
}
275-
276-
options = extend(
277-
{
278-
entity: apiEntity,
279-
role,
280-
},
281-
options);
282-
283-
const args = [options];
284-
285-
if (is.fn(callback)) {
286-
args.push(callback);
287-
}
288-
289-
return this[accessMethod].apply(this, args);
290-
};
293+
// tslint:disable-next-line:no-any
294+
(acc as any)[method] =
295+
(entityId: string, options: {}, callback: Function|{}) => {
296+
let apiEntity;
297+
298+
if (is.fn(options)) {
299+
callback = options;
300+
options = {};
301+
}
302+
303+
if (isPrefix) {
304+
apiEntity = entity + entityId;
305+
} else {
306+
// If the entity is not a prefix, it is a special entity group
307+
// that does not require further details. The accessor methods
308+
// only accept a callback.
309+
apiEntity = entity;
310+
callback = entityId;
311+
}
312+
313+
options = extend(
314+
{
315+
entity: apiEntity,
316+
role,
317+
},
318+
options);
319+
320+
const args = [options];
321+
322+
if (is.fn(callback)) {
323+
args.push(callback);
324+
}
325+
326+
// tslint:disable-next-line:no-any
327+
return (this as any)[accessMethod].apply(this, args);
328+
};
291329
});
292330

293331
return acc;
@@ -339,9 +377,9 @@ class AclRoleAccessorMethods {
339377
class Acl extends AclRoleAccessorMethods {
340378
default !: Acl;
341379
pathPrefix: string;
342-
request_;
380+
request_: typeof r;
343381

344-
constructor(options) {
382+
constructor(options: AclOptions) {
345383
super();
346384
this.pathPrefix = options.pathPrefix;
347385
this.request_ = options.request;
@@ -514,7 +552,10 @@ class Acl extends AclRoleAccessorMethods {
514552
* region_tag:storage_remove_file_owner
515553
* Example of removing an owner from a bucket:
516554
*/
517-
delete(options, callback?) {
555+
delete(options: RemoveAclOptions): Promise<RemoveAclResponse>;
556+
delete(options: RemoveAclOptions, callback: RemoveAclCallback): void;
557+
delete(options: RemoveAclOptions, callback?: RemoveAclCallback):
558+
void|Promise<RemoveAclResponse> {
518559
const query = {} as AclQuery;
519560

520561
if (options.generation) {
@@ -619,14 +660,19 @@ class Acl extends AclRoleAccessorMethods {
619660
* region_tag:storage_print_bucket_acl_for_user
620661
* Example of printing a bucket's ACL for a specific user:
621662
*/
622-
get(options, callback?) {
663+
get(options?: GetAclOptions): Promise<GetAclResponse>;
664+
get(options: GetAclOptions, callback: GetAclCallback): void;
665+
get(callback: GetAclCallback): void;
666+
get(optionsOrCallback?: GetAclOptions|GetAclCallback,
667+
cb?: GetAclCallback): void|Promise<GetAclResponse> {
668+
const options =
669+
typeof optionsOrCallback === 'object' ? optionsOrCallback : null;
670+
const callback =
671+
typeof optionsOrCallback === 'function' ? optionsOrCallback : cb;
623672
let path = '';
624673
const query = {} as AclQuery;
625674

626-
if (is.fn(options)) {
627-
callback = options;
628-
options = null;
629-
} else {
675+
if (options) {
630676
path = '/' + encodeURIComponent(options.entity);
631677

632678
if (options.generation) {
@@ -718,7 +764,10 @@ class Acl extends AclRoleAccessorMethods {
718764
* const apiResponse = data[1];
719765
* });
720766
*/
721-
update(options, callback?) {
767+
update(options: UpdateAclOptions): Promise<UpdateAclResponse>;
768+
update(options: UpdateAclOptions, callback: UpdateAclCallback): void;
769+
update(options: UpdateAclOptions, callback?: UpdateAclCallback):
770+
void|Promise<UpdateAclResponse> {
722771
const query = {} as AclQuery;
723772

724773
if (options.generation) {
@@ -753,7 +802,8 @@ class Acl extends AclRoleAccessorMethods {
753802
*
754803
* @private
755804
*/
756-
makeAclObject_(accessControlObject): AccessControlObject {
805+
makeAclObject_(accessControlObject: AccessControlObject):
806+
AccessControlObject {
757807
const obj = {
758808
entity: accessControlObject.entity,
759809
role: accessControlObject.role,

handwritten/storage/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {Bucket} from './bucket';
2929
import {Channel} from './channel';
3030
import {File} from './file';
3131
import {normalize} from './util';
32+
import {AccessControlObject} from './acl';
3233

3334
export interface GetServiceAccountOptions {
3435
userProject?: string;
@@ -764,4 +765,4 @@ promisifyAll(Storage, {
764765
*/
765766
export {Storage};
766767

767-
export {Bucket, File, Channel};
768+
export {Bucket, File, Channel, AccessControlObject};

handwritten/storage/system-test/storage.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,9 @@ import * as path from 'path';
2828
import * as through from 'through2';
2929
import * as tmp from 'tmp';
3030
import * as uuid from 'uuid';
31-
import * as r from 'request';
3231
import {util, ApiError, InstanceResponseCallback, BodyResponseCallback} from '@google-cloud/common';
33-
import {Storage, Bucket, File} from '../src';
34-
import {DeleteBucketCallback, UploadCallback} from '../src/bucket';
32+
import {Storage, Bucket, File, AccessControlObject} from '../src';
33+
import {DeleteBucketCallback} from '../src/bucket';
3534
import * as nock from 'nock';
3635
import {DeleteFileCallback} from '../src/file';
3736

@@ -208,7 +207,8 @@ describe('storage', () => {
208207
(err, accessControl) => {
209208
assert.ifError(err);
210209
assert.strictEqual(
211-
accessControl.role, storage.acl.OWNER_ROLE);
210+
(accessControl as AccessControlObject)!.role,
211+
storage.acl.OWNER_ROLE);
212212

213213
bucket.acl.default.update(
214214
{
@@ -218,7 +218,8 @@ describe('storage', () => {
218218
(err, accessControl) => {
219219
assert.ifError(err);
220220
assert.strictEqual(
221-
accessControl.role, storage.acl.READER_ROLE);
221+
(accessControl as AccessControlObject).role,
222+
storage.acl.READER_ROLE);
222223

223224
bucket.acl.default.delete(
224225
{entity: USER_ACCOUNT}, done);
@@ -249,7 +250,9 @@ describe('storage', () => {
249250

250251
bucket.acl.get(opts, (err, accessControl) => {
251252
assert.ifError(err);
252-
assert.strictEqual(accessControl.role, storage.acl.OWNER_ROLE);
253+
assert.strictEqual(
254+
(accessControl as AccessControlObject).role,
255+
storage.acl.OWNER_ROLE);
253256

254257
bucket.acl.delete(opts, done);
255258
});
@@ -274,7 +277,7 @@ describe('storage', () => {
274277
(err, accessControl) => {
275278
assert.ifError(err);
276279
assert.strictEqual(
277-
accessControl.role, storage.acl.WRITER_ROLE);
280+
accessControl!.role, storage.acl.WRITER_ROLE);
278281

279282
bucket.acl.delete({entity: USER_ACCOUNT}, done);
280283
});
@@ -343,8 +346,8 @@ describe('storage', () => {
343346
bucket.makePrivate(err => {
344347
assert.ifError(err);
345348
bucket.acl.get({entity: 'allUsers'}, (err, aclObject) => {
346-
assert.strictEqual(err.code, 404);
347-
assert.strictEqual(err.message, 'Not Found');
349+
assert.strictEqual((err as ApiError).code, 404);
350+
assert.strictEqual(err!.message, 'Not Found');
348351
assert.strictEqual(aclObject, null);
349352
done();
350353
});
@@ -577,8 +580,8 @@ describe('storage', () => {
577580
assert.ifError(err);
578581

579582
file!.acl.get({entity: 'allUsers'}, (err, aclObject) => {
580-
assert.strictEqual(err.code, 404);
581-
assert.strictEqual(err.message, 'Not Found');
583+
assert.strictEqual((err as ApiError)!.code, 404);
584+
assert.strictEqual(err!.message, 'Not Found');
582585
assert.strictEqual(aclObject, null);
583586
done();
584587
});

0 commit comments

Comments
 (0)