🐛 Set new Hubspot granular scopes (#2531)

* Hubspot Developer API Credentials: Use granular scopes as contacts scope is no longer available for new apps

*  Add new scopes to regular node

*  Small fix

*  Load contacts, companies and deals from API

Co-authored-by: that-one-tom <19203795+that-one-tom@users.noreply.github.com>
This commit is contained in:
Ricardo Espinoza 2021-12-10 14:28:59 -05:00 committed by GitHub
parent 8e2191b633
commit 1854d505b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 30 deletions

View file

@ -4,7 +4,12 @@ import {
} from 'n8n-workflow'; } from 'n8n-workflow';
const scopes = [ const scopes = [
'contacts', 'crm.objects.contacts.read',
'crm.schemas.contacts.read',
'crm.objects.companies.read',
'crm.schemas.companies.read',
'crm.objects.deals.read',
'crm.schemas.deals.read',
]; ];
export class HubspotDeveloperApi implements ICredentialType { export class HubspotDeveloperApi implements ICredentialType {

View file

@ -4,7 +4,16 @@ import {
} from 'n8n-workflow'; } from 'n8n-workflow';
const scopes = [ const scopes = [
'contacts', 'crm.schemas.deals.read',
'crm.objects.owners.read',
'crm.objects.contacts.write',
'crm.objects.companies.write',
'crm.objects.companies.read',
'crm.objects.deals.read',
'crm.schemas.contacts.read',
'crm.objects.deals.write',
'crm.objects.contacts.read',
'crm.schemas.companies.read',
'forms', 'forms',
'tickets', 'tickets',
]; ];

View file

@ -39,12 +39,16 @@ export async function hubspotApiRequest(this: IHookFunctions | IExecuteFunctions
return await this.helpers.request!(options); return await this.helpers.request!(options);
} else if (authenticationMethod === 'developerApi') { } else if (authenticationMethod === 'developerApi') {
const credentials = await this.getCredentials('hubspotDeveloperApi'); if (endpoint.includes('webhooks')) {
options.qs.hapikey = credentials!.apiKey as string; const credentials = await this.getCredentials('hubspotDeveloperApi');
return await this.helpers.request!(options); options.qs.hapikey = credentials!.apiKey as string;
return await this.helpers.request!(options);
} else {
return await this.helpers.requestOAuth2!.call(this, 'hubspotDeveloperApi', options, { tokenType: 'Bearer', includeCredentialsOnRefreshOnBody: true });
}
} else { } else {
// @ts-ignore
return await this.helpers.requestOAuth2!.call(this, 'hubspotOAuth2Api', options, { tokenType: 'Bearer', includeCredentialsOnRefreshOnBody: true }); return await this.helpers.requestOAuth2!.call(this, 'hubspotOAuth2Api', options, { tokenType: 'Bearer', includeCredentialsOnRefreshOnBody: true });
} }
} catch (error) { } catch (error) {

View file

@ -143,6 +143,9 @@ export class HubspotTrigger implements INodeType {
name: 'property', name: 'property',
type: 'options', type: 'options',
typeOptions: { typeOptions: {
loadOptionsDependsOn: [
'contact.propertyChange',
],
loadOptionsMethod: 'getContactProperties', loadOptionsMethod: 'getContactProperties',
}, },
displayOptions: { displayOptions: {
@ -160,6 +163,9 @@ export class HubspotTrigger implements INodeType {
name: 'property', name: 'property',
type: 'options', type: 'options',
typeOptions: { typeOptions: {
loadOptionsDependsOn: [
'company.propertyChange',
],
loadOptionsMethod: 'getCompanyProperties', loadOptionsMethod: 'getCompanyProperties',
}, },
displayOptions: { displayOptions: {
@ -177,6 +183,9 @@ export class HubspotTrigger implements INodeType {
name: 'property', name: 'property',
type: 'options', type: 'options',
typeOptions: { typeOptions: {
loadOptionsDependsOn: [
'deal.propertyChange',
],
loadOptionsMethod: 'getDealProperties', loadOptionsMethod: 'getDealProperties',
}, },
displayOptions: { displayOptions: {
@ -220,51 +229,48 @@ export class HubspotTrigger implements INodeType {
// select them easily // select them easily
async getContactProperties(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> { async getContactProperties(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = []; const returnData: INodePropertyOptions[] = [];
for (const field of contactFields) { const endpoint = '/properties/v2/contacts/properties';
const properties = await hubspotApiRequest.call(this, 'GET', endpoint, {});
for (const property of properties) {
const propertyName = property.label;
const propertyId = property.name;
returnData.push({ returnData.push({
name: capitalCase(field.label), name: propertyName,
value: field.id, value: propertyId,
}); });
} }
returnData.sort((a, b) => {
if (a.name < b.name) { return -1; }
if (a.name > b.name) { return 1; }
return 0;
});
return returnData; return returnData;
}, },
// Get all the available companies to display them to user so that he can // Get all the available companies to display them to user so that he can
// select them easily // select them easily
async getCompanyProperties(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> { async getCompanyProperties(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = []; const returnData: INodePropertyOptions[] = [];
for (const field of companyFields) { const endpoint = '/properties/v2/companies/properties';
const properties = await hubspotApiRequest.call(this, 'GET', endpoint, {});
for (const property of properties) {
const propertyName = property.label;
const propertyId = property.name;
returnData.push({ returnData.push({
name: capitalCase(field.label), name: propertyName,
value: field.id, value: propertyId,
}); });
} }
returnData.sort((a, b) => {
if (a.name < b.name) { return -1; }
if (a.name > b.name) { return 1; }
return 0;
});
return returnData; return returnData;
}, },
// Get all the available deals to display them to user so that he can // Get all the available deals to display them to user so that he can
// select them easily // select them easily
async getDealProperties(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> { async getDealProperties(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = []; const returnData: INodePropertyOptions[] = [];
for (const field of dealFields) { const endpoint = '/properties/v2/deals/properties';
const properties = await hubspotApiRequest.call(this, 'GET', endpoint, {});
for (const property of properties) {
const propertyName = property.label;
const propertyId = property.name;
returnData.push({ returnData.push({
name: capitalCase(field.label), name: propertyName,
value: field.id, value: propertyId,
}); });
} }
returnData.sort((a, b) => {
if (a.name < b.name) { return -1; }
if (a.name > b.name) { return 1; }
return 0;
});
return returnData; return returnData;
}, },
}, },