mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 04:04:06 -08:00
🐛 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:
parent
8e2191b633
commit
1854d505b8
|
@ -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 {
|
||||||
|
|
|
@ -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',
|
||||||
];
|
];
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue