Skip to content

Commit

Permalink
feat: PassThrough AuthClient (#1771)
Browse files Browse the repository at this point in the history
* feat: `PassThrough` AuthClient

* refactor: Expand Types
  • Loading branch information
danielbankhead authored Mar 12, 2024
1 parent 6a6e496 commit 0003bee
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 27 deletions.
7 changes: 2 additions & 5 deletions src/auth/authclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {Gaxios, GaxiosOptions, GaxiosPromise, GaxiosResponse} from 'gaxios';

import {DefaultTransporter, Transporter} from '../transporters';
import {Credentials} from './credentials';
import {Headers} from './oauth2client';
import {GetAccessTokenResponse, Headers} from './oauth2client';
import {OriginalAndCamel, originalOrCamelOptions} from '../util';

/**
Expand Down Expand Up @@ -128,10 +128,7 @@ export interface CredentialsClient {
* @return A promise that resolves with the current GCP access token
* response. If the current credential is expired, a new one is retrieved.
*/
getAccessToken(): Promise<{
token?: string | null;
res?: GaxiosResponse | null;
}>;
getAccessToken(): Promise<GetAccessTokenResponse>;

/**
* The main authentication interface. It takes an optional url which when
Expand Down
65 changes: 65 additions & 0 deletions src/auth/passthrough.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import {GaxiosOptions} from 'gaxios';
import {AuthClient} from './authclient';
import {GetAccessTokenResponse, Headers} from './oauth2client';

/**
* An AuthClient without any Authentication information. Useful for:
* - Anonymous access
* - Local Emulators
* - Testing Environments
*
*/
export class PassThroughClient extends AuthClient {
/**
* Creates a request without any authentication headers or checks.
*
* @remarks
*
* In testing environments it may be useful to change the provided
* {@link AuthClient.transporter} for any desired request overrides/handling.
*
* @param opts
* @returns The response of the request.
*/
async request<T>(opts: GaxiosOptions) {
return this.transporter.request<T>(opts);
}

/**
* A required method of the base class.
* Always will return an empty object.
*
* @returns {}
*/
async getAccessToken(): Promise<GetAccessTokenResponse> {
return {};
}

/**
* A required method of the base class.
* Always will return an empty object.
*
* @returns {}
*/
async getRequestHeaders(): Promise<Headers> {
return {};
}
}

const a = new PassThroughClient();

a.getAccessToken();
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export {
PluggableAuthClient,
PluggableAuthClientOptions,
} from './auth/pluggable-auth-client';
export {PassThroughClient} from './auth/passthrough';
export {DefaultTransporter} from './transporters';

const auth = new GoogleAuth();
Expand Down
25 changes: 3 additions & 22 deletions test/test.authclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,10 @@

import {strict as assert} from 'assert';

import {GaxiosOptions, GaxiosPromise, GaxiosResponse} from 'gaxios';
import {AuthClient} from '../src';
import {Headers} from '../src/auth/oauth2client';
import {PassThroughClient} from '../src';
import {snakeToCamel} from '../src/util';

describe('AuthClient', () => {
class TestAuthClient extends AuthClient {
request<T>(opts: GaxiosOptions): GaxiosPromise<T> {
throw new Error('Method not implemented.');
}

getRequestHeaders(url?: string | undefined): Promise<Headers> {
throw new Error('Method not implemented.');
}

getAccessToken(): Promise<{
token?: string | null | undefined;
res?: GaxiosResponse<any> | null | undefined;
}> {
throw new Error('Method not implemented.');
}
}

it('should accept and normalize snake case options to camel case', () => {
const expected = {
project_id: 'my-projectId',
Expand All @@ -49,11 +30,11 @@ describe('AuthClient', () => {
const camelCased = snakeToCamel(key) as keyof typeof authClient;

// assert snake cased input
let authClient = new TestAuthClient({[key]: value});
let authClient = new PassThroughClient({[key]: value});
assert.equal(authClient[camelCased], value);

// assert camel cased input
authClient = new TestAuthClient({[camelCased]: value});
authClient = new PassThroughClient({[camelCased]: value});
assert.equal(authClient[camelCased], value);
}
});
Expand Down
62 changes: 62 additions & 0 deletions test/test.passthroughclient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import {strict as assert} from 'assert';

import * as nock from 'nock';

import {PassThroughClient} from '../src';

describe('AuthClient', () => {
before(async () => {
nock.disableNetConnect();
});

afterEach(async () => {
nock.cleanAll();
});

describe('#getAccessToken', () => {
it('should return an empty object', async () => {
const client = new PassThroughClient();
const token = await client.getAccessToken();

assert.deepEqual(token, {});
});
});

describe('#getRequestHeaders', () => {
it('should return an empty object', async () => {
const client = new PassThroughClient();
const token = await client.getRequestHeaders();

assert.deepEqual(token, {});
});
});

describe('#request', () => {
it('should return the expected response', async () => {
const url = 'https://google.com';
const example = {test: 'payload'};
const scope = nock(url).get('/').reply(200, example);

const client = new PassThroughClient();
const response = await client.request({url});

assert.deepEqual(response.data, example);

scope.done();
});
});
});

0 comments on commit 0003bee

Please sign in to comment.