Hawk improvements and fuzzy filtering everywhere

This commit is contained in:
Gregory Schier 2017-08-21 11:11:52 -07:00
parent 2fcf98536f
commit 7c4800023e
9 changed files with 83 additions and 31 deletions

View File

@ -143,6 +143,9 @@ export const AUTH_HAWK = 'hawk';
export const AUTH_AWS_IAM = 'iam';
export const AUTH_NETRC = 'netrc';
export const HAWK_ALGORITHM_SHA256 = 'sha256';
export const HAWK_ALGORITHM_SHA1 = 'sha1';
const authTypesMap = {
[AUTH_BASIC]: ['Basic', 'Basic Auth'],
[AUTH_DIGEST]: ['Digest', 'Digest Auth'],

View File

@ -326,3 +326,9 @@ export function jsonParseOr (str: string, fallback: any): any {
export function escapeRegex (str: string): string {
return str.replace(ESCAPE_REGEX_MATCH, '\\$&');
}
export function fuzzyMatch (searchString: string, text: string): boolean {
const regexSearchString = escapeRegex(searchString.toLowerCase()).split('').join('.*');
const toMatch = new RegExp(regexSearchString);
return toMatch.test(text.toLowerCase());
}

View File

@ -1,6 +1,6 @@
// @flow
import type {BaseModel} from './index';
import {AUTH_BASIC, AUTH_DIGEST, AUTH_NONE, AUTH_NTLM, AUTH_OAUTH_2, AUTH_HAWK, AUTH_AWS_IAM, AUTH_NETRC, CONTENT_TYPE_FILE, CONTENT_TYPE_FORM_DATA, CONTENT_TYPE_FORM_URLENCODED, CONTENT_TYPE_OTHER, getContentTypeFromHeaders, METHOD_GET, CONTENT_TYPE_GRAPHQL, CONTENT_TYPE_JSON, METHOD_POST} from '../common/constants';
import {AUTH_BASIC, AUTH_DIGEST, AUTH_NONE, AUTH_NTLM, AUTH_OAUTH_2, AUTH_HAWK, AUTH_AWS_IAM, AUTH_NETRC, CONTENT_TYPE_FILE, CONTENT_TYPE_FORM_DATA, CONTENT_TYPE_FORM_URLENCODED, CONTENT_TYPE_OTHER, getContentTypeFromHeaders, METHOD_GET, CONTENT_TYPE_GRAPHQL, CONTENT_TYPE_JSON, METHOD_POST, HAWK_ALGORITHM_SHA256} from '../common/constants';
import * as db from '../common/database';
import {getContentTypeHeader} from '../common/misc';
import {buildFromParams, deconstructToParams} from '../common/querystring';
@ -118,7 +118,7 @@ export function newAuth (type: string, oldAuth: RequestAuthentication = {}): Req
// hawk
case AUTH_HAWK:
return {type, algorithm: 'sha256'};
return {type, algorithm: HAWK_ALGORITHM_SHA256};
// Types needing no defaults
default:

View File

@ -9,21 +9,32 @@
"author": "Insomnia <support@insomnia.rest>",
"main": "main.min.js",
"dependencies": {
"aws4": "^1.6.0",
"clone": "^2.1.0",
"deep-equal": "^1.0.1",
"electron-context-menu": "^0.9.0",
"electron-devtools-installer": "^2.2.0",
"electron-squirrel-startup": "^1.0.0",
"deep-equal": "^1.0.1",
"hawk": "^6.0.2",
"hkdf": "^0.0.2",
"html-entities": "^1.2.0",
"iconv-lite": "^0.4.15",
"insomnia-httpsnippet": "^1.16.5",
"insomnia-importers": "^1.3.9",
"insomnia-node-libcurl": "^1.2.3",
"jsonpath": "^0.2.11",
"marked": "^0.3.6",
"mkdirp": "^0.5.1",
"moment": "^2.18.1",
"mime-types": "^2.1.14",
"nedb": "^1.8.0",
"node-forge": "^0.7.0",
"simple-react-pdf": "^1.0.8",
"srp-js": "^0.2.0",
"tar": "^3.1.7",
"tough-cookie": "^2.3.1",
"vkbeautify": "^0.99.1"
"vkbeautify": "^0.99.1",
"whatwg-fetch": "^2.0.1",
"xmldom": "^0.1.22"
}
}

View File

@ -6,6 +6,7 @@ import classnames from 'classnames';
import DropdownButton from './dropdown-button';
import DropdownItem from './dropdown-item';
import DropdownDivider from './dropdown-divider';
import {fuzzyMatch} from '../../../../common/misc';
@autobind
class Dropdown extends PureComponent {
@ -59,7 +60,7 @@ class Dropdown extends PureComponent {
const listItemTextWithoutSpaces = listItem.textContent.toLowerCase().replace(/[^\w_]*/g, '');
const filterWithoutSpaces = newFilter.toLowerCase().replace(/[^\w_]*/g, '');
if (!newFilter || listItemTextWithoutSpaces.includes(filterWithoutSpaces)) {
if (!newFilter || fuzzyMatch(filterWithoutSpaces, listItemTextWithoutSpaces)) {
const filterIndex = listItem.getAttribute('data-filter-index');
filterItems.push(parseInt(filterIndex, 10));
}

View File

@ -1,10 +1,12 @@
// @flow
import type { Request } from '../../../../models/request';
import type {Request} from '../../../../models/request';
import React from 'react';
import autobind from 'autobind-decorator';
import OneLineEditor from '../../codemirror/one-line-editor';
import * as misc from '../../../../common/misc';
import {HAWK_ALGORITHM_SHA1, HAWK_ALGORITHM_SHA256} from '../../../../common/constants';
import HelpTooltip from '../../help-tooltip';
@autobind
class HawkAuth extends React.PureComponent {
@ -43,29 +45,69 @@ class HawkAuth extends React.PureComponent {
renderHawkAuthenticationFields (): Array<React.Element<*>> {
const hawkAuthId = this.renderInputRow(
'Hawk Auth ID',
'Auth ID',
'id',
this._handleChangeHawkAuthId
);
const hawkAuthKey = this.renderInputRow(
'Hawk Auth Key',
'Auth Key',
'key',
this._handleChangeHawkAuthKey
);
const algorithm = this.renderInputRow(
const algorithm = this.renderSelectRow(
'Algorithm',
'algorithm',
[
{name: HAWK_ALGORITHM_SHA256, value: HAWK_ALGORITHM_SHA256},
{name: HAWK_ALGORITHM_SHA1, value: HAWK_ALGORITHM_SHA1}
],
this._handleChangeAlgorithm
);
return [hawkAuthId, hawkAuthKey, algorithm];
}
renderInputRow (label: string,
property: string,
onChange: Function): React.Element<*> {
renderSelectRow (
label: string,
property: string,
options: Array<{name: string, value: string}>,
onChange: Function,
help: string | null = null
): React.Element<*> {
const {request} = this.props;
const id = label.replace(/ /g, '-');
const value = request.authentication.hasOwnProperty(property)
? request.authentication[property]
: options[0];
return (
<tr key={id}>
<td className="pad-right no-wrap valign-middle">
<label htmlFor={id} className="label--small no-pad">
{label}
{help && <HelpTooltip>{help}</HelpTooltip>}
</label>
</td>
<td className="wide">
<div className="form-control form-control--outlined no-margin">
<select id={id} onChange={onChange} value={value}>
{options.map(({name, value}) => (
<option key={value} value={value}>{name}</option>
))}
</select>
</div>
</td>
</tr>
);
}
renderInputRow (
label: string,
property: string,
onChange: Function
): React.Element<*> {
const {handleRender, handleGetRenderContext, request} = this.props;
const id = label.replace(/ /g, '-');
return (

View File

@ -8,6 +8,7 @@ import ModalHeader from '../base/modal-header';
import ModalBody from '../base/modal-body';
import MethodTag from '../tags/method-tag';
import * as models from '../../../models';
import {fuzzyMatch} from '../../../common/misc';
@autobind
class RequestSwitcherModal extends PureComponent {
@ -128,25 +129,14 @@ class RequestSwitcherModal extends PureComponent {
// OPTIMIZATION: This only filters if we have a filter
let matchedRequests = workspaceChildren.filter(d => d.type === models.request.type);
if (searchString) {
const specialCharacters = ['.', '^', '$', '*', '+', '-', '?', '(', ')', '[', ']', '{', '}', '\\', '|'];
const regexSearchString = searchString
.toLowerCase()
.split('')
.map((c) => specialCharacters.includes(c) ? `\\${c}` : c)
.join('.*');
const toMatch = new RegExp(regexSearchString);
matchedRequests = matchedRequests.filter(r => {
const name = r.name.toLowerCase();
const id = r._id.toLowerCase();
// Fuzzy match searchString to name
const matchesName = toMatch.test(name);
const matchesName = fuzzyMatch(searchString, name);
// Match exact Id
const matchesId = id === toMatch;
const matchesId = r._id === searchString;
return matchesName || matchesId;
});

View File

@ -1,4 +1,5 @@
import {createSelector} from 'reselect';
import {fuzzyMatch} from '../../common/misc';
// ~~~~~~~~~ //
// Selectors //
@ -106,13 +107,13 @@ export const selectSidebarChildren = createSelector(
// Build the monster string to match on
const method = child.doc.method || '';
const name = child.doc.name;
const toMatch = `${method}${name}${parentNames.join('❅')}`.toLowerCase();
const toMatch = `${method}${name}${parentNames.join('❅')}`;
// Try to match name
let hasMatchedName = true;
for (const token of sidebarFilter.trim().toLowerCase().split(' ')) {
for (const token of sidebarFilter.trim().split(' ')) {
// Filter failed. Don't render children
if (toMatch.indexOf(token) === -1) {
if (!fuzzyMatch(token, toMatch)) {
hasMatchedName = false;
break;
}

View File

@ -59,8 +59,6 @@ module.exports = {
// To get jsonlint working...
'file', 'system'
],
plugins: [
new webpack.optimize.ModuleConcatenationPlugin(),
],
plugins: [],
target: 'electron-renderer'
};