Skip to content

Commit

Permalink
feat(auth,messages,server-client): Made auth handlers async (#801)
Browse files Browse the repository at this point in the history
  • Loading branch information
dragonmantank authored Mar 2, 2023
1 parent 141c4b8 commit 0fa9d7f
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 106 deletions.
102 changes: 51 additions & 51 deletions packages/auth/__tests__/auth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,63 +11,63 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import { Auth } from '../lib'
import fs from 'fs'
import { Auth } from '../lib';
import fs from 'fs';

const apiKey = '12345'
const apiSecret = 'ABCDE'
const applicationId = '1234'
const apiKey = '12345';
const apiSecret = 'ABCDE';
const applicationId = '1234';
const privateKeyString = fs
.readFileSync(`${__dirname}/private.test.key`)
.toString()
.readFileSync(`${__dirname}/private.test.key`)
.toString();

describe('Auth Object', () => {
test('should store API Key and Secret from object', () => {
let auth = new Auth({ apiKey, apiSecret })
expect(auth.apiKey).toEqual(apiKey)
expect(auth.apiSecret).toEqual(apiSecret)
})
test('should store API Key and Secret from object', () => {
const auth = new Auth({ apiKey, apiSecret });
expect(auth.apiKey).toEqual(apiKey);
expect(auth.apiSecret).toEqual(apiSecret);
});

test('should convert privateKey buffer to a string', () => {
let auth = new Auth({
applicationId: '1234',
privateKey: fs.readFileSync(`${__dirname}/private.test.key`),
})
expect(auth.applicationId).toEqual(applicationId)
expect(auth.privateKey).toEqual(privateKeyString)
})
test('should convert privateKey buffer to a string', () => {
const auth = new Auth({
applicationId: '1234',
privateKey: fs.readFileSync(`${__dirname}/private.test.key`),
});
expect(auth.applicationId).toEqual(applicationId);
expect(auth.privateKey).toEqual(privateKeyString);
});

test('should use a private key string directly', () => {
let auth = new Auth({
applicationId: '1234',
privateKey: fs
.readFileSync(`${__dirname}/private.test.key`)
.toString(),
})
expect(auth.applicationId).toEqual(applicationId)
expect(auth.privateKey).toEqual(privateKeyString)
})
test('should use a private key string directly', () => {
const auth = new Auth({
applicationId: '1234',
privateKey: fs
.readFileSync(`${__dirname}/private.test.key`)
.toString(),
});
expect(auth.applicationId).toEqual(applicationId);
expect(auth.privateKey).toEqual(privateKeyString);
});

test('should convert file path into private key string', () => {
const privateKeyString = fs
.readFileSync(`${__dirname}/private.test.key`)
.toString()
const auth = new Auth({
applicationId: '1234',
privateKey: `${__dirname}/private.test.key`,
})
expect(auth.applicationId).toEqual(applicationId)
expect(auth.privateKey).toEqual(privateKeyString)
})
})
test('should convert file path into private key string', () => {
const privateKeyString = fs
.readFileSync(`${__dirname}/private.test.key`)
.toString();
const auth = new Auth({
applicationId: '1234',
privateKey: `${__dirname}/private.test.key`,
});
expect(auth.applicationId).toEqual(applicationId);
expect(auth.privateKey).toEqual(privateKeyString);
});
});

describe('Auth Methods', () => {
test('should return query params with getQueryParams', () => {
let params = {
api_key: apiKey,
api_secret: apiSecret,
}
let auth = new Auth({ apiKey, apiSecret })
expect(auth.getQueryParams()).toEqual(params)
})
})
test('should return query params with getQueryParams', async () => {
const params = {
api_key: apiKey,
api_secret: apiSecret,
};
const auth = new Auth({ apiKey, apiSecret });
expect(await auth.getQueryParams()).toEqual(params);
});
});
10 changes: 6 additions & 4 deletions packages/auth/lib/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,24 @@ export class Auth implements AuthInterface {
}
}

getQueryParams = <T>(params?: T): AuthQueryParams & T => {
getQueryParams = async <T>(params?: T): Promise<AuthQueryParams & T> => {
return { api_key: this.apiKey, api_secret: this.apiSecret, ...params };
};

createBasicHeader = () => {
createBasicHeader = async () => {
log('Creating basic auth header');
const buf = Buffer.from(`${this.apiKey}:${this.apiSecret}`);
return 'Basic ' + buf.toString('base64');
};

createBearerHeader = () => {
createBearerHeader = async () => {
log('Creating bearer header');
return 'Bearer ' + tokenGenerate(this.applicationId, this.privateKey);
};

createSignatureHash = <T>(params: T): AuthSignedParams & T => {
createSignatureHash = async <T>(
params: T,
): Promise<AuthSignedParams & T> => {
log('Creating signature hash');
const returnParams: AuthSignedParams & T = Object.assign(
{ api_key: this.apiKey },
Expand Down
8 changes: 4 additions & 4 deletions packages/auth/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ export interface AuthInterface {
signature?: SignedHashParams
applicationId?: string
privateKey?: string
getQueryParams<T>(params?: T): AuthQueryParams & T
createSignatureHash<T>(params: T): AuthSignedParams & T
createBasicHeader(): string
createBearerHeader(): string
getQueryParams<T>(params?: T): Promise<AuthQueryParams & T>
createSignatureHash<T>(params: T): Promise<AuthSignedParams & T>
createBasicHeader(): Promise<string>
createBearerHeader(): Promise<string>
}
79 changes: 41 additions & 38 deletions packages/messages/lib/messages.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,54 @@
import { Client } from '@vonage/server-client'
import { MessageObject } from './interfaces/MessageObject'
import { MessagesSendResponse } from './types'
import { Client } from '@vonage/server-client';
import { MessageObject } from './interfaces/MessageObject';
import { MessagesSendResponse } from './types';

const stripUndefined = (obj) => {
for (const key in obj) {
if (typeof obj[key] === 'object') {
obj[key] = stripUndefined(obj[key])
} else if (!obj[key]) {
delete obj[key]
}
for (const key in obj) {
if (typeof obj[key] === 'object') {
obj[key] = stripUndefined(obj[key]);
} else if (!obj[key]) {
delete obj[key];
}
}

return obj
}
return obj;
};

export class Messages extends Client {
/**
/**
* Handle various ways the Messages API handles auth
* The Messages API handles both JWT (preferred) as well as Basic so we
* cannot just set a local authType
*
* @param {any} request - Object containing request data
*/
public addAuthenticationToRequest(request: any) {
if (this.auth.applicationId && this.auth.privateKey) {
request.headers = Object.assign({}, request.headers, {
Authorization: this.auth.createBearerHeader(),
})
} else if (this.auth.signature) {
request.data = Object.assign(
request.data,
this.auth.createSignatureHash(request.data)
)
} else {
request.data = Object.assign(
request.data,
this.auth.getQueryParams(request.data)
)
}

return request
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public async addAuthenticationToRequest(request: any) {
if (this.auth.applicationId && this.auth.privateKey) {
request.headers = Object.assign({}, request.headers, {
Authorization: await this.auth.createBearerHeader(),
});
} else if (this.auth.signature) {
request.data = Object.assign(
request.data,
await this.auth.createSignatureHash(request.data),
);
} else {
request.data = Object.assign(
request.data,
await this.auth.getQueryParams(request.data),
);
}

public async send(message: MessageObject) {
const data = stripUndefined(message)
const resp = await this.sendPostRequest<MessagesSendResponse>(
`${this.config.apiHost}/v1/messages`,
data
)
return resp.data
}
return request;
}

public async send(message: MessageObject) {
const data = stripUndefined(message);
const resp = await this.sendPostRequest<MessagesSendResponse>(
`${this.config.apiHost}/v1/messages`,
data,
);
return resp.data;
}
}
4 changes: 2 additions & 2 deletions packages/server-client/__tests__/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe('server client', () => {
const client = new MockClient(
new Auth({ apiKey: 'abcd', apiSecret: '1234' }),
);
const request = client.addAuthenticationToRequest({
const request = await client.addAuthenticationToRequest({
method: 'GET',
params: { foo: 'bar' },
});
Expand All @@ -38,7 +38,7 @@ describe('server client', () => {
const client = new MockClient(
new Auth({ apiKey: 'abcd', apiSecret: '1234' }),
);
const request = client.addAuthenticationToRequest({
const request = await client.addAuthenticationToRequest({
method: 'POST',
data: { foo: 'bar' },
});
Expand Down
21 changes: 14 additions & 7 deletions packages/server-client/lib/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,26 @@ export abstract class Client {

public static transformers = transfomers;

public addAuthenticationToRequest(request: any): any {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public async addAuthenticationToRequest(request: any): Promise<any> {
log(`adding ${this.authType || 'api key/secret'} to request`);
switch (this.authType) {
case AuthenticationType.BASIC:
request.headers = Object.assign({}, request.headers, {
Authorization: this.auth.createBasicHeader(),
Authorization: await this.auth.createBasicHeader(),
});
break;
case AuthenticationType.JWT:
request.headers = Object.assign({}, request.headers, {
Authorization: this.auth.createBearerHeader(),
Authorization: await this.auth.createBearerHeader(),
});
break;
case AuthenticationType.QUERY_KEY_SECRET:
request.params = request.params || {};
request.params = Object.assign(
{},
request.params,
this.auth.getQueryParams(request.params),
await this.auth.getQueryParams(request.params),
);
break;
case AuthenticationType.KEY_SECRET:
Expand All @@ -82,14 +83,14 @@ export abstract class Client {
request.params = Object.assign(
{},
request.params,
this.auth.getQueryParams(request.params),
await this.auth.getQueryParams(request.params),
);
} else {
request.data = request.data || {};
request.data = Object.assign(
{},
request.data,
this.auth.getQueryParams(request.data),
await this.auth.getQueryParams(request.data),
);
}
break;
Expand All @@ -109,6 +110,7 @@ export abstract class Client {

public async sendFormSubmitRequest<T>(
url: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
payload?: { [key: string]: any },
): Promise<VetchResponse<T>> {
const request = {
Expand All @@ -129,6 +131,7 @@ export abstract class Client {

public async sendGetRequest<T>(
url: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
queryParams?: { [key: string]: any },
): Promise<VetchResponse<T>> {
const request = {
Expand All @@ -146,6 +149,7 @@ export abstract class Client {

public async sendPatchRequest<T>(
url: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
payload?: { [key: string]: any },
): Promise<VetchResponse<T>> {
const request = {
Expand All @@ -166,6 +170,7 @@ export abstract class Client {

public async sendPostRequest<T>(
url: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
payload?: { [key: string]: any },
): Promise<VetchResponse<T>> {
const request = {
Expand All @@ -186,6 +191,7 @@ export abstract class Client {

public async sendPutRequest<T>(
url: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
payload?: { [key: string]: any },
): Promise<VetchResponse<T>> {
const request = {
Expand All @@ -204,8 +210,9 @@ export abstract class Client {
return await this.sendRequest<T>(request);
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
public async sendRequest<T>(request: any): Promise<VetchResponse<T>> {
request = this.addAuthenticationToRequest(request);
request = await this.addAuthenticationToRequest(request);
request.timeout = this.config.timeout;
const result = await vetchRequest<T>(request);
return result;
Expand Down

0 comments on commit 0fa9d7f

Please sign in to comment.