From 6affc13d9961552e8f200af314bff2b369d474d8 Mon Sep 17 00:00:00 2001 From: Ian K Smith Date: Mon, 25 May 2020 14:48:24 -0600 Subject: [PATCH] Add 'UtilsModule' & 'parseAuthorizationHeader' helper (#39) * Add 'UtilModule' & 'parseTokenFromBearerString' helper * Update CHANGELOG * Rename 'UtilModule' to 'UtilsModule' * Reflect nomenclature changes in CHANGELOG --- CHANGELOG.md | 6 ++++++ src/core/sdk-exceptions.ts | 7 +++++++ src/core/sdk.ts | 7 +++++++ src/modules/users/index.ts | 2 +- src/modules/utils/index.ts | 15 +++++++++++++++ src/types/exception-types.ts | 1 + .../sdk-exceptions/error-factories.spec.ts | 11 +++++++++++ test/spec/core/sdk/constructor.spec.ts | 2 ++ .../utils/parseAuthorizationHeader.spec.ts | 18 ++++++++++++++++++ 9 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 src/modules/utils/index.ts create mode 100644 test/spec/modules/utils/parseAuthorizationHeader.spec.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cdd3bc..02da6b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,12 @@ - ... +## `1.1.0` - 05/25/2020 + +#### Added + +- Introduced `UtilsModule` along with a `parseAuthorizationHeader` helper method. + ## `1.0.0` - 04/09/2020 This is the first release our changelog records. Future updates will be logged in the following format: diff --git a/src/core/sdk-exceptions.ts b/src/core/sdk-exceptions.ts index 99f9ffb..11b4abb 100644 --- a/src/core/sdk-exceptions.ts +++ b/src/core/sdk-exceptions.ts @@ -49,3 +49,10 @@ export function createServiceError(...nestedErrors: any[]) { nestedErrors, ); } + +export function createExpectedBearerStringError() { + return new MagicAdminSDKError( + ErrorCode.ExpectedBearerString, + 'Expected argumenet to be a string in the `Bearer {token}` format.', + ); +} diff --git a/src/core/sdk.ts b/src/core/sdk.ts index 5dbd293..5557da8 100644 --- a/src/core/sdk.ts +++ b/src/core/sdk.ts @@ -1,5 +1,6 @@ import { TokenModule } from '../modules/token'; import { UsersModule } from '../modules/users'; +import { UtilsModule } from '../modules/utils'; import { MagicAdminSDKAdditionalConfiguration } from '../types'; export class MagicAdminSDK { @@ -17,6 +18,11 @@ export class MagicAdminSDK { */ public readonly users: UsersModule; + /** + * Contains general utilities for Magic Admin SDK. + */ + public readonly utils: UtilsModule; + constructor(public readonly secretApiKey?: string, options?: MagicAdminSDKAdditionalConfiguration) { const endpoint = options?.endpoint ?? 'https://api.magic.link'; this.apiBaseUrl = endpoint.replace(/\/+$/, ''); @@ -24,5 +30,6 @@ export class MagicAdminSDK { // Assign API Modules this.token = new TokenModule(this); this.users = new UsersModule(this); + this.utils = new UtilsModule(this); } } diff --git a/src/modules/users/index.ts b/src/modules/users/index.ts index 8ee9b4c..b0899db 100644 --- a/src/modules/users/index.ts +++ b/src/modules/users/index.ts @@ -1,7 +1,7 @@ import { BaseModule } from '../base-module'; import { createApiKeyMissingError } from '../../core/sdk-exceptions'; import { post, get } from '../../utils/rest'; -import { generateIssuerFromPublicAddress, parsePublicAddressFromIssuer } from '../../utils/issuer'; +import { generateIssuerFromPublicAddress } from '../../utils/issuer'; import { MagicUserMetadata } from '../../types'; export class UsersModule extends BaseModule { diff --git a/src/modules/utils/index.ts b/src/modules/utils/index.ts new file mode 100644 index 0000000..c829e86 --- /dev/null +++ b/src/modules/utils/index.ts @@ -0,0 +1,15 @@ +import { BaseModule } from '../base-module'; +import { createExpectedBearerStringError } from '../../core/sdk-exceptions'; + +export class UtilsModule extends BaseModule { + /** + * Parse a raw DID Token from the given Authorization header. + */ + public parseAuthorizationHeader(header: string) { + if (!header.toLowerCase().startsWith('bearer ')) { + throw createExpectedBearerStringError(); + } + + return header.substring(7); + } +} diff --git a/src/types/exception-types.ts b/src/types/exception-types.ts index 03a0a60..d97692f 100644 --- a/src/types/exception-types.ts +++ b/src/types/exception-types.ts @@ -6,4 +6,5 @@ export enum ErrorCode { ApiKeyMissing = 'ERROR_SECRET_API_KEY_MISSING', MalformedTokenError = 'ERROR_MALFORMED_TOKEN', ServiceError = 'SERVICE_ERROR', + ExpectedBearerString = 'EXPECTED_BEARER_STRING', } diff --git a/test/spec/core/sdk-exceptions/error-factories.spec.ts b/test/spec/core/sdk-exceptions/error-factories.spec.ts index 5f7f5b5..77e9791 100644 --- a/test/spec/core/sdk-exceptions/error-factories.spec.ts +++ b/test/spec/core/sdk-exceptions/error-factories.spec.ts @@ -8,6 +8,7 @@ import { createFailedRecoveringProofError, createApiKeyMissingError, createServiceError, + createExpectedBearerStringError, } from '../../../../src/core/sdk-exceptions'; function errorAssertions>( @@ -73,3 +74,13 @@ test('#06: Creates `SERVICE_ERROR` error with non-empty `data` property', async ['hello', 'world'], ); }); + +test('#07: Creates `EXPECTED_BEARER_STRING` error', async t => { + const error = createExpectedBearerStringError(); + errorAssertions( + t, + error, + 'EXPECTED_BEARER_STRING', + 'Expected argumenet to be a string in the `Bearer {token}` format.', + ); +}); diff --git a/test/spec/core/sdk/constructor.spec.ts b/test/spec/core/sdk/constructor.spec.ts index 32af3e9..ba15830 100644 --- a/test/spec/core/sdk/constructor.spec.ts +++ b/test/spec/core/sdk/constructor.spec.ts @@ -5,6 +5,7 @@ import { MagicAdminSDK } from '../../../../src/core/sdk'; import { API_FULL_URL, API_KEY } from '../../../lib/constants'; import { TokenModule } from '../../../../src/modules/token'; import { UsersModule } from '../../../../src/modules/users'; +import { UtilsModule } from '../../../../src/modules/utils'; test.serial('#01: Initialize `MagicAdminSDK`', t => { const magic = new MagicAdminSDK(API_KEY); @@ -22,6 +23,7 @@ test.serial('#02: Initialize `MagicAdminSDK` with custom endpoint', t => { t.is(magic.apiBaseUrl, 'https://example.com'); t.true(magic.token instanceof TokenModule); t.true(magic.users instanceof UsersModule); + t.true(magic.utils instanceof UtilsModule); }); test.serial('#03: Strips trailing slash(es) from custom endpoint argument', t => { diff --git a/test/spec/modules/utils/parseAuthorizationHeader.spec.ts b/test/spec/modules/utils/parseAuthorizationHeader.spec.ts new file mode 100644 index 0000000..f7a3ee1 --- /dev/null +++ b/test/spec/modules/utils/parseAuthorizationHeader.spec.ts @@ -0,0 +1,18 @@ +import test from 'ava'; +import { createMagicAdminSDK } from '../../../lib/factories'; +import { VALID_DIDT } from '../../../lib/constants'; +import { createExpectedBearerStringError, MagicAdminSDKError } from '../../../../src/core/sdk-exceptions'; + +test('#01: Successfully parses raw DIDT from `Bearer` authorization header', async t => { + const sdk = createMagicAdminSDK(); + const result = sdk.utils.parseAuthorizationHeader(`Bearer ${VALID_DIDT}`); + t.deepEqual(result, VALID_DIDT); +}); + +test('#02: Raises error if header is in the wrong format', async t => { + const sdk = createMagicAdminSDK(); + const expectedError = createExpectedBearerStringError(); + const error: MagicAdminSDKError = t.throws(() => sdk.utils.parseAuthorizationHeader(`Ooops ${VALID_DIDT}`)); + t.is(error.code, expectedError.code); + t.is(error.message, expectedError.message); +});