-
Notifications
You must be signed in to change notification settings - Fork 66
zapier convert: Add support for basic auth mapping #200
Changes from 6 commits
cdd046b
e48ae43
e6bd39a
fba8369
e1fdd11
0a2b0f9
88ed299
7ac3941
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,7 @@ | ||
<% if (before && !session && !oauth) { %>const maybeIncludeAuth = (request, z, bundle) => { | ||
<% if (customBasic) { %> | ||
const { replaceVars } = require('./utils'); | ||
<% } %> | ||
<% if (before && !session && !oauth && !customBasic) { %>const maybeIncludeAuth = (request, z, bundle) => { | ||
<% | ||
Object.keys(mapping).forEach((mapperKey) => { | ||
fields.forEach((field) => { | ||
|
@@ -14,6 +17,18 @@ | |
%> | ||
return request; | ||
}; | ||
<% } else if (customBasic) { %> | ||
const maybeIncludeAuth = (request, z, bundle) => { | ||
const mapping = { | ||
username: '<%= mapping.username %>', | ||
password: '<%= mapping.password %>' | ||
}; | ||
const username = replaceVars(mapping.username, bundle); | ||
const password = replaceVars(mapping.password, bundle); | ||
const encoded = `${username}:${password}`.toString('base64'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
request.headers.Authorization = `Baisc ${encoded}`; | ||
return request; | ||
}; | ||
<% } | ||
|
||
if (before && session) { %>const maybeIncludeAuth = (request, z, bundle) => { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -120,7 +120,7 @@ describe('convert render functions', () => { | |
const wbDef = definitions.noAuth; | ||
return convert.renderIndex(wbDef) | ||
.then(string => { | ||
string.should.containEql('authentication: {}'); | ||
string.should.not.containEql('authentication:'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Originally, we generated an empty |
||
convert.hasAuth(wbDef).should.be.false(); | ||
}); | ||
}); | ||
|
@@ -131,7 +131,7 @@ describe('convert render functions', () => { | |
return convert.renderAuth(wbDef) | ||
.then(string => { | ||
const auth = loadAuthModuleFromString(string); | ||
auth.type.should.eql('basic'); | ||
auth.type.should.eql('custom'); | ||
auth.fields.should.eql([ | ||
{ | ||
key: 'username', | ||
|
@@ -157,7 +157,7 @@ describe('convert render functions', () => { | |
return convert.renderAuth(wbDef) | ||
.then(string => { | ||
const auth = loadAuthModuleFromString(string); | ||
auth.type.should.eql('basic'); | ||
auth.type.should.eql('custom'); | ||
auth.fields.should.eql([ | ||
{ | ||
key: 'username', | ||
|
@@ -202,14 +202,12 @@ describe('convert render functions', () => { | |
|
||
return convert.getHeader(wbDef) | ||
.then(string => { | ||
string.should.eql(`const maybeIncludeAuth = (request, z, bundle) => { | ||
string.trim().should.eql(`const maybeIncludeAuth = (request, z, bundle) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
request.headers['Authorization'] = bundle.authData['api_key']; | ||
|
||
return request; | ||
}; | ||
|
||
`); | ||
};`); | ||
}); | ||
}); | ||
|
||
|
@@ -238,14 +236,12 @@ describe('convert render functions', () => { | |
|
||
return convert.getHeader(wbDef) | ||
.then(string => { | ||
string.should.eql(`const maybeIncludeAuth = (request, z, bundle) => { | ||
string.trim().should.eql(`const maybeIncludeAuth = (request, z, bundle) => { | ||
|
||
request.params['api_key'] = bundle.authData['api_key']; | ||
|
||
return request; | ||
}; | ||
|
||
`); | ||
};`); | ||
}); | ||
}); | ||
|
||
|
@@ -281,7 +277,7 @@ describe('convert render functions', () => { | |
|
||
return convert.getHeader(wbDef) | ||
.then(string => { | ||
string.should.eql(`const maybeIncludeAuth = (request, z, bundle) => { | ||
string.trim().should.eql(`const maybeIncludeAuth = (request, z, bundle) => { | ||
|
||
request.headers['X-Token'] = bundle.authData.sessionKey; | ||
|
||
|
@@ -320,9 +316,7 @@ const getSessionKey = (z, bundle) => { | |
sessionKey: firstKeyValue | ||
}; | ||
}); | ||
}; | ||
|
||
`); | ||
};`); | ||
}); | ||
}); | ||
|
||
|
@@ -371,14 +365,12 @@ const getSessionKey = (z, bundle) => { | |
|
||
return convert.getHeader(wbDef) | ||
.then(string => { | ||
string.should.eql(`const maybeIncludeAuth = (request, z, bundle) => { | ||
string.trim().should.eql(`const maybeIncludeAuth = (request, z, bundle) => { | ||
|
||
request.headers.Authorization = \`Bearer \${bundle.authData.access_token}\`; | ||
|
||
return request; | ||
}; | ||
|
||
`); | ||
};`); | ||
}); | ||
}); | ||
|
||
|
@@ -493,14 +485,12 @@ const getSessionKey = (z, bundle) => { | |
|
||
return convert.getHeader(wbDef) | ||
.then(string => { | ||
string.should.eql(`const maybeIncludeAuth = (request, z, bundle) => { | ||
string.trim().should.eql(`const maybeIncludeAuth = (request, z, bundle) => { | ||
|
||
request.headers.Authorization = \`Bearer \${bundle.authData.access_token}\`; | ||
|
||
return request; | ||
}; | ||
|
||
`); | ||
};`); | ||
}); | ||
}); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -95,7 +95,7 @@ const getAuthType = (definition) => { | |
}; | ||
|
||
const hasAuth = (definition) => { | ||
return getAuthType(definition) !== 'custom' || !_.isEmpty(definition.auth_fields); | ||
return getAuthType(definition) !== 'custom' && !_.isEmpty(definition.auth_fields); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixes the logic determining if an app has auth. |
||
}; | ||
|
||
const renderField = (definition, key, indent = 0) => { | ||
|
@@ -199,6 +199,10 @@ const renderAuthTemplate = (authType, definition) => { | |
const testTriggerKey = getTestTriggerKey(definition); | ||
const { hasGetConnectionLabelScripting } = getAuthMetaData(definition); | ||
|
||
if (authType === 'basic' && !_.isEmpty(definition.general.auth_mapping)) { | ||
authType = 'custom'; | ||
} | ||
|
||
const templateContext = { | ||
TEST_TRIGGER_MODULE: `./triggers/${snakeCase(testTriggerKey)}`, | ||
TYPE: authType, | ||
|
@@ -446,11 +450,17 @@ const getMetaData = (definition) => { | |
}); | ||
}); | ||
|
||
const hasBefore = (type === 'api-header' || type === 'api-query' || type === 'session' || type === 'oauth2' || type === 'oauth2-refresh'); | ||
const hasAfter = (type === 'session'); | ||
const needsAuth = hasAuth(definition); | ||
const isCustomBasic = (needsAuth && type === 'basic' && !_.isEmpty(definition.general.auth_mapping)); | ||
const hasBefore = needsAuth && ( | ||
type === 'api-header' || type === 'api-query' || type === 'session' || | ||
type === 'oauth2' || type === 'oauth2-refresh' || isCustomBasic | ||
); | ||
const hasAfter = (needsAuth && type === 'session'); | ||
const fieldsOnQuery = (authPlacement === 'params' || type === 'api-query'); | ||
const isSession = (type === 'session'); | ||
const isOAuth = (type === 'oauth2' || type === 'oauth2-refresh'); | ||
const isSession = (needsAuth && type === 'session'); | ||
const isOAuth = needsAuth && (type === 'oauth2' || type === 'oauth2-refresh'); | ||
|
||
const needsLegacyScriptingRunner = isSession || hasAnyScriptingMethods; | ||
|
||
return { | ||
|
@@ -460,6 +470,7 @@ const getMetaData = (definition) => { | |
fieldsOnQuery, | ||
isSession, | ||
isOAuth, | ||
isCustomBasic, | ||
needsLegacyScriptingRunner, | ||
}; | ||
}; | ||
|
@@ -472,6 +483,7 @@ const getHeader = (definition) => { | |
hasAfter, | ||
isSession, | ||
isOAuth, | ||
isCustomBasic, | ||
fieldsOnQuery, | ||
} = getMetaData(definition); | ||
|
||
|
@@ -481,6 +493,7 @@ const getHeader = (definition) => { | |
after: hasAfter, | ||
session: isSession, | ||
oauth: isOAuth, | ||
customBasic: isCustomBasic, | ||
fields: Object.keys(definition.auth_fields), | ||
mapping: _.get(definition, ['general', 'auth_mapping'], {}), | ||
query: fieldsOnQuery, | ||
|
@@ -585,15 +598,20 @@ const writeStep = (type, definition, key, legacyApp, newAppDir) => { | |
}; | ||
|
||
// render the authData used in the trigger/search/create test code | ||
const renderAuthData = (authType) => { | ||
const renderAuthData = (definition) => { | ||
const authType = getAuthType(definition); | ||
let result; | ||
switch (authType) { | ||
case 'basic': | ||
case 'basic': { | ||
let lines = _.map(definition.auth_fields, (field, key) => { | ||
const upperKey = key.toUpperCase(); | ||
return ` ${key}: process.env.${upperKey}`; | ||
}); | ||
result = `{ | ||
username: process.env.USERNAME, | ||
password: process.env.PASSWORD | ||
${lines.join(',\n')} | ||
}`; | ||
break; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the generated test code, we were assuming basic auth is always username and password, which is not true. We should really take advantage of |
||
case 'oauth2': | ||
result = `{ | ||
access_token: process.env.ACCESS_TOKEN | ||
|
@@ -626,9 +644,8 @@ const renderAuthData = (authType) => { | |
}; | ||
|
||
const renderStepTest = (type, definition, key, legacyApp) => { | ||
const authType = getAuthType(legacyApp); | ||
const label = definition.label || _.capitalize(key); | ||
const authData = renderAuthData(authType); | ||
const authData = renderAuthData(legacyApp); | ||
const templateContext = { | ||
KEY: key, | ||
LABEL: label, | ||
|
@@ -661,15 +678,15 @@ const writeUtils = (newAppDir) => { | |
}; | ||
|
||
const renderIndex = (legacyApp) => { | ||
const _hasAuth = hasAuth(legacyApp); | ||
const needsAuth = hasAuth(legacyApp); | ||
const templateContext = { | ||
HEADER: '', | ||
TRIGGERS: '', | ||
SEARCHES: '', | ||
CREATES: '', | ||
BEFORE_REQUESTS: getBeforeRequests(legacyApp), | ||
AFTER_RESPONSES: getAfterResponses(legacyApp), | ||
hasAuth: _hasAuth | ||
needsAuth, | ||
}; | ||
|
||
return getHeader(legacyApp) | ||
|
@@ -678,7 +695,7 @@ const renderIndex = (legacyApp) => { | |
|
||
const importLines = []; | ||
|
||
if (_hasAuth) { | ||
if (needsAuth) { | ||
importLines.push("const authentication = require('./authentication');"); | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use the term "custom basic" to indicate a basic authentication that does not use username and password as user-facing authentication fields.