diff --git a/src/auth/authclient.ts b/src/auth/authclient.ts index 12033203..29e1602a 100644 --- a/src/auth/authclient.ts +++ b/src/auth/authclient.ts @@ -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'; /** @@ -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; /** * The main authentication interface. It takes an optional url which when diff --git a/src/auth/passthrough.ts b/src/auth/passthrough.ts new file mode 100644 index 00000000..bde50cba --- /dev/null +++ b/src/auth/passthrough.ts @@ -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(opts: GaxiosOptions) { + return this.transporter.request(opts); + } + + /** + * A required method of the base class. + * Always will return an empty object. + * + * @returns {} + */ + async getAccessToken(): Promise { + return {}; + } + + /** + * A required method of the base class. + * Always will return an empty object. + * + * @returns {} + */ + async getRequestHeaders(): Promise { + return {}; + } +} + +const a = new PassThroughClient(); + +a.getAccessToken(); diff --git a/src/index.ts b/src/index.ts index 5225dd53..77ad950a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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(); diff --git a/test/test.authclient.ts b/test/test.authclient.ts index 786d4d04..2faa0f15 100644 --- a/test/test.authclient.ts +++ b/test/test.authclient.ts @@ -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(opts: GaxiosOptions): GaxiosPromise { - throw new Error('Method not implemented.'); - } - - getRequestHeaders(url?: string | undefined): Promise { - throw new Error('Method not implemented.'); - } - - getAccessToken(): Promise<{ - token?: string | null | undefined; - res?: GaxiosResponse | 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', @@ -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); } }); diff --git a/test/test.passthroughclient.ts b/test/test.passthroughclient.ts new file mode 100644 index 00000000..19a15387 --- /dev/null +++ b/test/test.passthroughclient.ts @@ -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(); + }); + }); +});