mirror of
https://github.com/Kong/insomnia.git
synced 2026-05-25 09:10:40 -04:00
Add hash template tag (#560)
This commit is contained in:
@@ -5,7 +5,7 @@ import {globalBeforeEach} from '../../../__jest__/before-each';
|
||||
function assertTemplate (txt, context, expected) {
|
||||
return async function () {
|
||||
const result = await templating.render(txt, {context});
|
||||
expect(result).toMatch(expected);
|
||||
expect(result).toBe(expected);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ describe('FileExtension', () => {
|
||||
beforeEach(globalBeforeEach);
|
||||
const ctx = {path: path.resolve(__dirname, path.join('./test.txt'))};
|
||||
const escapedPath = ctx.path.replace(/\\/g, '\\\\');
|
||||
it('reads from string', assertTemplate(`{% file "${escapedPath}" %}`, ctx, 'Hello World'));
|
||||
it('reads from string', assertTemplate(`{% file "${escapedPath}" %}`, ctx, 'Hello World!'));
|
||||
it('reads a file correctly', assertTemplate('{% file path %}', ctx, 'Hello World!'));
|
||||
it('fails on missing file', assertTemplateFails('{% file "/foo" %}', ctx, `ENOENT: no such file or directory, open '${path.resolve('/foo')}'`));
|
||||
it('fails on no 2nd param', assertTemplateFails('{% file %}', ctx, 'No file selected'));
|
||||
|
||||
73
app/templating/extensions/__tests__/hash-extension.test.js
Normal file
73
app/templating/extensions/__tests__/hash-extension.test.js
Normal file
@@ -0,0 +1,73 @@
|
||||
import * as templating from '../../index';
|
||||
import {globalBeforeEach} from '../../../__jest__/before-each';
|
||||
|
||||
function assertTemplate (txt, expected) {
|
||||
return async function () {
|
||||
const result = await templating.render(txt);
|
||||
expect(result).toBe(expected);
|
||||
};
|
||||
}
|
||||
|
||||
function assertTemplateFails (txt, expected) {
|
||||
return async function () {
|
||||
try {
|
||||
await templating.render(txt);
|
||||
fail(`Render should have thrown ${expected}`);
|
||||
} catch (err) {
|
||||
expect(err.message).toContain(expected);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
describe('FileExtension', () => {
|
||||
beforeEach(globalBeforeEach);
|
||||
// Algorithms
|
||||
it('hashes sha1', assertTemplate(
|
||||
'{% hash "sha1", "hex", "foo" %}',
|
||||
'0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'
|
||||
));
|
||||
it('hashes sha256', assertTemplate(
|
||||
'{% hash "sha256", "hex", "foo" %}',
|
||||
'2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae'
|
||||
));
|
||||
it('hashes md5', assertTemplate(
|
||||
'{% hash "md5", "hex", "foo" %}',
|
||||
'acbd18db4cc2f85cedef654fccc4a4d8'
|
||||
));
|
||||
it('fails to hash invalid algorithm', assertTemplateFails(
|
||||
'{% hash "bad", "hex", "foo" %}',
|
||||
'Digest method not supported'
|
||||
));
|
||||
|
||||
// Digests
|
||||
it('hashes to latin1', assertTemplate(
|
||||
'{% hash "md5", "latin1", "foo" %}',
|
||||
'¬½ÛLÂø\\íïeOÌĤØ'
|
||||
));
|
||||
it('hashes to hex', assertTemplate(
|
||||
'{% hash "md5", "hex", "foo" %}',
|
||||
'acbd18db4cc2f85cedef654fccc4a4d8'
|
||||
));
|
||||
it('hashes to base64', assertTemplate(
|
||||
'{% hash "md5", "base64", "foo" %}',
|
||||
'rL0Y20zC+Fzt72VPzMSk2A=='
|
||||
));
|
||||
it('fails to hash to invalid', assertTemplateFails(
|
||||
'{% hash "md5", "bad", "foo" %}',
|
||||
'Invalid encoding bad. Choices are hex, latin1, base64'
|
||||
));
|
||||
|
||||
// Values
|
||||
it('hashes empty string', assertTemplate(
|
||||
'{% hash "md5", "hex", "" %}',
|
||||
'd41d8cd98f00b204e9800998ecf8427e'
|
||||
));
|
||||
it('hashes no string', assertTemplate(
|
||||
'{% hash "md5", "hex" %}',
|
||||
'd41d8cd98f00b204e9800998ecf8427e'
|
||||
));
|
||||
it('fails to hash non string', assertTemplateFails(
|
||||
'{% hash "md5", "hex", true %}',
|
||||
'Cannot hash value of type "boolean"'
|
||||
));
|
||||
});
|
||||
49
app/templating/extensions/hash-extension.js
Normal file
49
app/templating/extensions/hash-extension.js
Normal file
@@ -0,0 +1,49 @@
|
||||
// @flow
|
||||
import crypto from 'crypto';
|
||||
import type {PluginTemplateTag} from './index';
|
||||
|
||||
export default ({
|
||||
name: 'hash',
|
||||
displayName: 'Hash',
|
||||
description: 'Apply hash to a value',
|
||||
args: [
|
||||
{
|
||||
displayName: 'Algorithm',
|
||||
type: 'enum',
|
||||
options: [
|
||||
{displayName: 'MD5', value: 'md5'},
|
||||
{displayName: 'SHA1', value: 'sha1'},
|
||||
{displayName: 'SHA256', value: 'sha256'},
|
||||
{displayName: 'SHA512', value: 'sha512'}
|
||||
]
|
||||
},
|
||||
{
|
||||
displayName: 'Digest Encoding',
|
||||
description: 'The encoding of the output',
|
||||
type: 'enum',
|
||||
options: [
|
||||
{displayName: 'Hexadecimal', value: 'hex'},
|
||||
{displayName: 'Base64', value: 'base64'}
|
||||
]
|
||||
},
|
||||
{
|
||||
displayName: 'Input',
|
||||
type: 'string',
|
||||
placeholder: 'Value to hash'
|
||||
}
|
||||
],
|
||||
run (context: Object, algorithm: string, encoding: string, value: string = ''): string {
|
||||
if (encoding !== 'hex' && encoding !== 'latin1' && encoding !== 'base64') {
|
||||
throw new Error(`Invalid encoding ${encoding}. Choices are hex, latin1, base64`);
|
||||
}
|
||||
|
||||
const valueType = typeof value;
|
||||
if (valueType !== 'string') {
|
||||
throw new Error(`Cannot hash value of type "${valueType}"`);
|
||||
}
|
||||
|
||||
const hash = crypto.createHash(algorithm);
|
||||
hash.update(value || '', 'utf8');
|
||||
return hash.digest(encoding);
|
||||
}
|
||||
}: PluginTemplateTag);
|
||||
@@ -7,6 +7,7 @@ import nowExtension from './now-extension';
|
||||
import fileExtension from './file-extension';
|
||||
import responseExtension from './response-extension';
|
||||
import base64Extension from './base-64-extension';
|
||||
import hashExtension from './hash-extension';
|
||||
import requestExtension from './request-extension';
|
||||
import type {NunjucksParsedTagArg} from '../utils';
|
||||
import type {Request} from '../../models/request';
|
||||
@@ -24,8 +25,8 @@ type PluginArgumentBase = {
|
||||
|
||||
export type PluginArgumentEnumOption = {
|
||||
displayName: DisplayName,
|
||||
description: string,
|
||||
value: PluginArgumentValue,
|
||||
description?: string,
|
||||
placeholder?: string
|
||||
}
|
||||
|
||||
@@ -96,10 +97,11 @@ export type PluginTemplateTag = {
|
||||
|
||||
const DEFAULT_EXTENSIONS: Array<PluginTemplateTag> = [
|
||||
timestampExtension,
|
||||
fileExtension,
|
||||
nowExtension,
|
||||
uuidExtension,
|
||||
base64Extension,
|
||||
fileExtension,
|
||||
hashExtension,
|
||||
requestExtension,
|
||||
responseExtension
|
||||
];
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// @flow
|
||||
import uuid from 'uuid';
|
||||
import type {PluginTemplateTag} from './index';
|
||||
|
||||
export default {
|
||||
export default ({
|
||||
displayName: 'UUID',
|
||||
name: 'uuid',
|
||||
description: 'generate v1 or v4 UUIDs',
|
||||
@@ -30,4 +32,4 @@ export default {
|
||||
throw new Error(`Invalid UUID type "${uuidType}"`);
|
||||
}
|
||||
}
|
||||
};
|
||||
}: PluginTemplateTag);
|
||||
|
||||
@@ -384,8 +384,9 @@ class TagEditor extends React.PureComponent<Props, State> {
|
||||
<select value={value} onChange={this._handleChange}>
|
||||
{options.map(option => {
|
||||
let label: string;
|
||||
if (option.description) {
|
||||
label = `${fnOrString(option.displayName, argDatas)} – ${option.description}`;
|
||||
const {description} = option;
|
||||
if (description) {
|
||||
label = `${fnOrString(option.displayName, argDatas)} – ${description}`;
|
||||
} else {
|
||||
label = fnOrString(option.displayName, argDatas);
|
||||
}
|
||||
|
||||
3
flow-typed/uuid.js
vendored
3
flow-typed/uuid.js
vendored
@@ -1,5 +1,6 @@
|
||||
declare module 'uuid' {
|
||||
declare module.exports: {
|
||||
v4: () => string
|
||||
v4: () => string,
|
||||
v1: () => string
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user