Skip to content

Commit

Permalink
improvement: perform runtime validations on user config
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Apr 20, 2020
1 parent 453b987 commit 7a91c36
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 34 deletions.
20 changes: 7 additions & 13 deletions adonis-typings/hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ declare module '@ioc:Adonis/Core/Hash' {
/**
* Default list of available drivers. One can you reference this type
* to setup the `HashersList`.
*
* We will remove this later. Make sure all stubs are not using this
* type.
*/
export type HashDrivers = {
bcrypt: {
Expand Down Expand Up @@ -112,39 +115,30 @@ declare module '@ioc:Adonis/Core/Hash' {
list: { [P in keyof HashersList]: HashersList[P]['config'] },
}

/**
* Piggy back on the driver method when driver exists, otherwise fallback to `never`
*/
export type DriverMethod<T, K extends keyof HashDriverContract> = T extends HashDriverContract
? HashDriverContract[K]
: never

/**
* Hash mananger interface
*/
export interface HashContract<
DefaultDriver = HashersList[HashConfig['default']]['implementation']
> extends ManagerContract<
export interface HashContract extends ManagerContract<
HashDriverContract,
HashDriverContract,
{ [P in keyof HashersList]: HashersList[P]['implementation'] }
> {
/**
* Hash plain text value using the default mapping
*/
hash (value: string): ReturnType<DriverMethod<DefaultDriver, 'hash'>>
hash (value: string): ReturnType<HashDriverContract['hash']>

/**
* Verify plain value against the hashed value to find if it's
* valid or not
*/
verify (hashedValue: string, plainValue: string): ReturnType<DriverMethod<DefaultDriver, 'verify'>>
verify (hashedValue: string, plainValue: string): ReturnType<HashDriverContract['verify']>

/**
* Check the hash against the current config to find it needs
* to be re-hashed or not
*/
needsReHash (hashedValue: string): ReturnType<DriverMethod<DefaultDriver, 'needsReHash'>>
needsReHash (hashedValue: string): ReturnType<HashDriverContract['needsReHash']>
}

const Hash: HashContract
Expand Down
28 changes: 11 additions & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"@adonisjs/mrm-preset": "^2.3.0",
"@phc/argon2": "^1.0.9",
"@phc/bcrypt": "^1.0.2",
"@types/node": "^13.13.0",
"@types/node": "^13.13.1",
"argon2": "^0.26.2",
"bcrypt": "^4.0.1",
"commitizen": "^4.0.4",
Expand Down Expand Up @@ -83,7 +83,8 @@
},
"dependencies": {
"@phc/format": "^0.5.0",
"@poppinss/manager": "^2.1.6"
"@poppinss/manager": "^2.1.6",
"@poppinss/utils": "^2.2.6"
},
"optionalDependencies": {
"@phc/argon2": "^1.0.9",
Expand Down
16 changes: 14 additions & 2 deletions src/Hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
/// <reference path="../adonis-typings/hash.ts" />

import { Manager } from '@poppinss/manager'
import { ManagerConfigValidator } from '@poppinss/utils'

import {
HashConfig,
HashersList,
Expand All @@ -25,9 +27,19 @@ export class Hash <Config extends HashConfig> extends Manager<
HashDriverContract,
HashDriverContract,
{ [P in keyof HashersList]: HashersList[P]['implementation'] }
> implements HashContract<HashDriverContract> {
> implements HashContract {
constructor (container: any, public config: Config) {
super(container)
this.validateConfig()
}

/**
* Validate config
*/
private validateConfig () {
const validator = new ManagerConfigValidator(this.config, 'hash', 'config/hash')
validator.validateDefault('default')
validator.validateList('list', 'default')
}

protected $cacheMappings = true
Expand All @@ -36,7 +48,7 @@ export class Hash <Config extends HashConfig> extends Manager<
* Pulling the default driver name from the user config.
*/
protected getDefaultMappingName (): string {
return this.config.default
return this.config.default!
}

/**
Expand Down
25 changes: 25 additions & 0 deletions test/hash.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ test.group('Hash', () => {
test('create extended driver', async (assert) => {
const hash = new Hash({}, Object.assign({}, config, {
list: {
bcrypt: {},
foo: {
driver: 'my-algo',
},
Expand Down Expand Up @@ -88,4 +89,28 @@ test.group('Hash', () => {

assert.instanceOf(hash.use('foo'), MyAlgo)
})

test('raise exception when default driver is missing', async (assert) => {
const hash = () => new Hash({}, {} as any)
assert.throw(
hash,
'Invalid "hash" config. Missing value for "default". Make sure set it inside "config/hash',
)
})

test('raise exception when list is missing', async (assert) => {
const hash = () => new Hash({}, { default: 'bcrypt' } as any)
assert.throw(
hash,
'Invalid "hash" config. Missing value for "list". Make sure set it inside "config/hash',
)
})

test('raise exception when default driver value is missing inside list', async (assert) => {
const hash = () => new Hash({}, { default: 'bcrypt', list: {} } as any)
assert.throw(
hash,
'Invalid "hash" config. "bcrypt" is not defined inside "list". Make sure set it inside "config/hash',
)
})
})

0 comments on commit 7a91c36

Please sign in to comment.