-
-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(api-v3): add apiKey command and pass API key to protected services
On July 18th, 2019, Troy Hunt moved the haveibeenpwned.com API to v3 and protected several services behind authentication, requiring an API key. See his blog post here: https://www.troyhunt.com/authentication-and-the-have-i-been-pwned-api/ BREAKING CHANGE: Several of the haveibeenpwned.com services now require an API key from https://haveibeenpwned.com/API/Key. See [Troy's blog post](https://www.troyhunt.com/authentication-and-the-have-i-been-pwned-api/) for rationale and a full explanation. Once you have obtained your API key, you must run "pwned apiKey <your-key>" to configure `pwned` so that it may use it in future requests made to protected endpoints. Some commands, like `pw`, do not require an API key and will continue to function without one. Thus, you may continue to use `pwned` without an API key, as long as you only care about the commands that do not require one. Each command indicates if it requires an API key in the help for the specific command.
- Loading branch information
Showing
9 changed files
with
228 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { Argv, CommandBuilder } from 'yargs'; | ||
import { oneLine } from 'common-tags'; | ||
import config from '../utils/config'; | ||
import logger from '../utils/logger'; | ||
|
||
export const command = 'apiKey <key>'; | ||
export const describe = 'set the API key to be used for authenticated requests'; | ||
|
||
interface ApiKeyArgvOptions { | ||
key: string; | ||
} | ||
|
||
interface ApiKeyHandlerOptions { | ||
key: string; | ||
} | ||
|
||
export const builder: CommandBuilder< | ||
ApiKeyArgvOptions, | ||
ApiKeyHandlerOptions | ||
> /* istanbul ignore next */ = (yargs): Argv<ApiKeyHandlerOptions> => | ||
yargs | ||
.positional('key', { type: 'string' }) | ||
.demandOption('key') | ||
.check(argv => { | ||
if (!argv.key.length) { | ||
throw new Error('The key argument must not be empty.'); | ||
} | ||
return true; | ||
}) | ||
.group(['h', 'v'], 'Global Options:').epilog(oneLine` | ||
Please obtain an API key from https://haveibeenpwned.com/API/Key and then | ||
run "pwned apiKey <key>" to configure pwned. | ||
`); | ||
|
||
/** | ||
* Stores the user's specified API key to be used for future requests to | ||
* authenticated endpoints. | ||
* | ||
* @param {object} argv the parsed argv object | ||
* @param {string} argv.key the user's API key | ||
* @returns {Promise<void>} the resulting Promise where output is rendered | ||
*/ | ||
export const handler = async ({ key }: ApiKeyHandlerOptions): Promise<void> => { | ||
try { | ||
config.set('apiKey', key); | ||
if (config.get('apiKey') === key) { | ||
logger.log(oneLine` | ||
✔ API key saved successfully. It will be used in future requests made | ||
to haveibeenpwned.com services that require authentication. | ||
`); | ||
} else { | ||
throw new Error(oneLine` | ||
✖ API key mismatch: the key read back from config does not match the | ||
key supplied! | ||
`); | ||
} | ||
} catch (err) { | ||
logger.error(err.message); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import Conf from 'conf'; | ||
|
||
const config = new Conf<string>({ | ||
schema: { | ||
apiKey: { type: 'string' }, | ||
}, | ||
}); | ||
|
||
export default config; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import translateApiError from './translateApiError'; | ||
|
||
describe('util: getErrorMessage', () => { | ||
it('returns a custom error message if input matches "hibp-api-key"', () => { | ||
const orig = 'something something hibp-api-key and stuff'; | ||
expect(translateApiError(orig)).not.toBe(orig); | ||
}); | ||
|
||
it("returns the original message if it doesn't need interpreted", () => { | ||
const orig = 'stuff broke'; | ||
expect(translateApiError(orig)).toBe(orig); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { oneLine } from 'common-tags'; | ||
|
||
const translateApiError = (originalMessage: string): string => { | ||
const errMsg = /hibp-api-key/.test(originalMessage) | ||
? oneLine` | ||
Access denied due to invalid or missing API key. Please obtain an API | ||
key from https://haveibeenpwned.com/API/Key and then run "pwned apiKey | ||
<key>" to configure pwned. | ||
` | ||
: originalMessage; | ||
|
||
return errMsg; | ||
}; | ||
|
||
export default translateApiError; |
Oops, something went wrong.