Skip to content

Commit

Permalink
fix(KoboToolbox Node): Improve attachment matching logic and GeoJSON …
Browse files Browse the repository at this point in the history
…Polygon format (#3535)

* Fix query,sort + use question name in attachments

* Change Menu structure

* kobo: Clearer webhook name

* [kobo]: fix when no json filter

* Fix ambiguous attachment matching + GeoJSON Polygon format

* Fix kobo function

* Fix extra descriptions

* Add credentials injection and testing

* Fix credential injection and lint issues

Co-authored-by: Yann Jouanique <yann.jouanique@oneacrefund.org>
Co-authored-by: Yann Jouanique <yann.jouanique@gmail.com>
Co-authored-by: Omar Ajoue <krynble@gmail.com>
Co-authored-by: Jan Oberhauser <janober@users.noreply.github.com>
  • Loading branch information
5 people authored Jul 4, 2022
1 parent 725d122 commit 637e815
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 41 deletions.
18 changes: 18 additions & 0 deletions packages/nodes-base/credentials/KoBoToolboxApi.credentials.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import {
IAuthenticateGeneric,
ICredentialTestRequest,
ICredentialType,
NodePropertyTypes,
} from 'n8n-workflow';
Expand All @@ -23,4 +25,20 @@ export class KoBoToolboxApi implements ICredentialType {
hint: 'You can get your API token at https://[api-root]/token/?format=json (for a logged in user)',
},
];
authenticate = {
type: 'generic',
properties: {
headers: {
Authorization: '=Token {{$credentials.token}}',
},
},
} as IAuthenticateGeneric;

test: ICredentialTestRequest = {
request: {
baseURL: '={{$credentials.URL}}',
url: '/api/v2/assets/',
method: 'GET',
},
};
}
9 changes: 4 additions & 5 deletions packages/nodes-base/nodes/KoBoToolbox/GenericFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export async function koBoToolboxApiRequest(this: IExecuteFunctions | IWebhookFu
url: '',
headers: {
'Accept': 'application/json',
'Authorization': `Token ${credentials.token}`,
},
json: true,
};
Expand All @@ -44,7 +43,7 @@ export async function koBoToolboxApiRequest(this: IExecuteFunctions | IWebhookFu
let results = null;
let keepLooking = true;
while (keepLooking) {
const response = await this.helpers.httpRequest(options);
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'koBoToolboxApi', options);
// Append or set results
results = response.results ? _.concat(results || [], response.results) : response;
if (returnAll && response.next) {
Expand Down Expand Up @@ -106,7 +105,7 @@ const formatValue = (value: any, format: string): any => { //tslint:disable-line
return _.first(points) === _.last(points)
? {
type: 'Polygon',
coordinates: [coordinates]
coordinates: [coordinates],
}
: {
type: 'LineString',
Expand Down Expand Up @@ -183,12 +182,12 @@ export async function downloadAttachments(this: IExecuteFunctions | IWebhookFunc

let relatedQuestion = null;
if('question' === options.binaryNamingScheme) {
for(let question of Object.keys(submission)) {
for(const question of Object.keys(submission)) {
// The logic to map attachments to question is sometimes ambiguous:
// - If the attachment is linked to a question, the question's value is the same as the attachment's filename (with spaces replaced by underscores)
// - BUT sometimes the attachment's filename has an extra suffix, e.g. "My_Picture_0OdlaKJ.jpg", would map to the question "picture": "My Picture.jpg"
const sanitizedQuestionValue = _.toString(submission[question]).replace(/\s/g, '_'); // replace spaces with underscores
if (sanitizedFileName == sanitizedQuestionValue) {
if (sanitizedFileName === sanitizedQuestionValue) {
relatedQuestion = question;
// Just use the first match...
break;
Expand Down
36 changes: 0 additions & 36 deletions packages/nodes-base/nodes/KoBoToolbox/KoBoToolbox.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ export class KoBoToolbox implements INodeType {
{
name: 'koBoToolboxApi',
required: true,
testedBy: 'koBoToolboxApiCredentialTest',
},
],
properties: [
Expand Down Expand Up @@ -91,41 +90,6 @@ export class KoBoToolbox implements INodeType {
};

methods = {
credentialTest: {
async koBoToolboxApiCredentialTest(this: ICredentialTestFunctions, credential: ICredentialsDecrypted): Promise<INodeCredentialTestResult> {
const credentials = credential.data;
try {
const response = await this.helpers.request({
url: `${credentials!.URL}/api/v2/assets/hash`,
headers: {
'Accept': 'application/json',
'Authorization': `Token ${credentials!.token}`,
},
json: true,
});

if (response.hash) {
return {
status: 'OK',
message: 'Connection successful!',
};
}
else {
return {
status: 'Error',
message: `Credentials are not valid. Response: ${response.detail}`,
};
}
}
catch (err) {
return {
status: 'Error',
message: `Credentials validation failed: ${(err as JsonObject).message}`,
};
}
},
},

loadOptions: {
loadForms,
},
Expand Down

0 comments on commit 637e815

Please sign in to comment.