n8n-nodes-base
Version:
Base nodes of n8n
581 lines • 31.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Zammad = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const descriptions_1 = require("./descriptions");
const GenericFunctions_1 = require("./GenericFunctions");
class Zammad {
description = {
displayName: 'Zammad',
name: 'zammad',
icon: 'file:zammad.svg',
group: ['input'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Consume the Zammad API',
defaults: {
name: 'Zammad',
},
usableAsTool: true,
inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
credentials: [
{
name: 'zammadBasicAuthApi',
required: true,
testedBy: 'zammadBasicAuthApiTest',
displayOptions: {
show: {
authentication: ['basicAuth'],
},
},
},
{
name: 'zammadTokenAuthApi',
required: true,
testedBy: 'zammadTokenAuthApiTest',
displayOptions: {
show: {
authentication: ['tokenAuth'],
},
},
},
],
properties: [
{
displayName: 'Authentication',
name: 'authentication',
type: 'options',
options: [
{
name: 'Basic Auth',
value: 'basicAuth',
},
{
name: 'Token Auth',
value: 'tokenAuth',
},
],
default: 'tokenAuth',
},
{
displayName: 'Resource',
name: 'resource',
noDataExpression: true,
type: 'options',
options: [
{
name: 'Group',
value: 'group',
},
{
name: 'Organization',
value: 'organization',
},
{
name: 'Ticket',
value: 'ticket',
},
{
name: 'User',
value: 'user',
},
],
default: 'user',
},
...descriptions_1.groupDescription,
...descriptions_1.organizationDescription,
...descriptions_1.ticketDescription,
...descriptions_1.userDescription,
],
};
methods = {
loadOptions: {
// ----------------------------------
// custom fields
// ----------------------------------
async loadGroupCustomFields() {
const allFields = await GenericFunctions_1.getAllFields.call(this);
return (0, GenericFunctions_1.getGroupCustomFields)(allFields).map(GenericFunctions_1.fieldToLoadOption);
},
async loadOrganizationCustomFields() {
const allFields = await GenericFunctions_1.getAllFields.call(this);
return (0, GenericFunctions_1.getOrganizationCustomFields)(allFields).map(GenericFunctions_1.fieldToLoadOption);
},
async loadUserCustomFields() {
const allFields = await GenericFunctions_1.getAllFields.call(this);
return (0, GenericFunctions_1.getUserCustomFields)(allFields).map(GenericFunctions_1.fieldToLoadOption);
},
async loadTicketCustomFields() {
const allFields = await GenericFunctions_1.getAllFields.call(this);
return (0, GenericFunctions_1.getTicketCustomFields)(allFields).map(GenericFunctions_1.fieldToLoadOption);
},
// ----------------------------------
// built-in fields
// ----------------------------------
async loadGroupFields() {
const allFields = await GenericFunctions_1.getAllFields.call(this);
return (0, GenericFunctions_1.getGroupFields)(allFields).map(GenericFunctions_1.fieldToLoadOption);
},
async loadOrganizationFields() {
const allFields = await GenericFunctions_1.getAllFields.call(this);
return (0, GenericFunctions_1.getOrganizationFields)(allFields).map(GenericFunctions_1.fieldToLoadOption);
},
async loadTicketFields() {
const allFields = await GenericFunctions_1.getAllFields.call(this);
return (0, GenericFunctions_1.getTicketFields)(allFields).map(GenericFunctions_1.fieldToLoadOption);
},
async loadUserFields() {
const allFields = await GenericFunctions_1.getAllFields.call(this);
return (0, GenericFunctions_1.getUserFields)(allFields).map(GenericFunctions_1.fieldToLoadOption);
},
// ----------------------------------
// resources
// ----------------------------------
// by non-ID attribute
/**
* POST /tickets requires group name instead of group ID.
*/
async loadGroupNames() {
const groups = (await GenericFunctions_1.zammadApiRequest.call(this, 'GET', '/groups'));
return groups.map((i) => ({ name: i.name, value: i.name }));
},
/**
* PUT /users requires organization name instead of organization ID.
*/
async loadOrganizationNames() {
const orgs = (await GenericFunctions_1.zammadApiRequest.call(this, 'GET', '/organizations'));
return orgs.filter(GenericFunctions_1.isNotZammadFoundation).map((i) => ({ name: i.name, value: i.name }));
},
/**
* POST /tickets requires customer email instead of customer ID.
*/
async loadCustomerEmails() {
const users = (await GenericFunctions_1.zammadApiRequest.call(this, 'GET', '/users'));
return users.filter(GenericFunctions_1.isCustomer).map((i) => ({ name: i.email, value: i.email }));
},
// by ID
/**
* PUT /tickets requires customer ID instead of customer email.
* Zammad API constraint: Any listings will return users own information only. -> https://docs.zammad.org/en/latest/api/user.html
*/
async loadCustomerIds() {
const users = (await GenericFunctions_1.zammadApiRequest.call(this, 'GET', '/users'));
return users.filter(GenericFunctions_1.isCustomer).map((i) => ({ name: i.email, value: i.id }));
},
async loadGroups() {
const groups = (await GenericFunctions_1.zammadApiRequest.call(this, 'GET', '/groups'));
return groups.map((i) => ({ name: i.name, value: i.id }));
},
async loadOrganizations() {
const orgs = (await GenericFunctions_1.zammadApiRequest.call(this, 'GET', '/organizations'));
return orgs.filter(GenericFunctions_1.isNotZammadFoundation).map((i) => ({ name: i.name, value: i.id }));
},
async loadUsers() {
const users = (await GenericFunctions_1.zammadApiRequest.call(this, 'GET', '/users'));
return users.filter(GenericFunctions_1.doesNotBelongToZammad).map((i) => ({ name: i.login, value: i.id }));
},
async loadTicketStates() {
const states = (await GenericFunctions_1.zammadApiRequest.call(this, 'GET', '/ticket_states'));
return states.map((state) => ({ name: state.name, value: state.id }));
},
async loadTicketPriorities() {
const priorities = (await GenericFunctions_1.zammadApiRequest.call(this, 'GET', '/ticket_priorities'));
return priorities.map((priority) => ({ name: priority.name, value: priority.id }));
},
},
credentialTest: {
async zammadBasicAuthApiTest(credential) {
const credentials = credential.data;
const baseUrl = (0, GenericFunctions_1.tolerateTrailingSlash)(credentials.baseUrl);
const options = {
method: 'GET',
uri: `${baseUrl}/api/v1/users/me`,
json: true,
rejectUnauthorized: !credentials.allowUnauthorizedCerts,
auth: {
user: credentials.username,
pass: credentials.password,
},
};
try {
await this.helpers.request(options);
return {
status: 'OK',
message: 'Authentication successful',
};
}
catch (error) {
return {
status: 'Error',
message: error.message,
};
}
},
async zammadTokenAuthApiTest(credential) {
const credentials = credential.data;
const baseUrl = (0, GenericFunctions_1.tolerateTrailingSlash)(credentials.baseUrl);
const options = {
method: 'GET',
uri: `${baseUrl}/api/v1/users/me`,
json: true,
rejectUnauthorized: !credentials.allowUnauthorizedCerts,
headers: {
Authorization: `Token token=${credentials.accessToken}`,
},
};
try {
await this.helpers.request(options);
return {
status: 'OK',
message: 'Authentication successful',
};
}
catch (error) {
return {
status: 'Error',
message: error.message,
};
}
},
},
};
async execute() {
const items = this.getInputData();
const resource = this.getNodeParameter('resource', 0);
const operation = this.getNodeParameter('operation', 0);
let responseData;
const returnData = [];
for (let i = 0; i < items.length; i++) {
try {
if (resource === 'user') {
// **********************************************************************
// user
// **********************************************************************
if (operation === 'create') {
// ----------------------------------
// user:create
// ----------------------------------
// https://docs.zammad.org/en/latest/api/user.html#create
const body = {
firstname: this.getNodeParameter('firstname', i),
lastname: this.getNodeParameter('lastname', i),
};
const { addressUi, customFieldsUi, ...rest } = this.getNodeParameter('additionalFields', i);
Object.assign(body, addressUi?.addressDetails);
customFieldsUi?.customFieldPairs.forEach((pair) => {
body[pair.name] = pair.value;
});
Object.assign(body, rest);
responseData = await GenericFunctions_1.zammadApiRequest.call(this, 'POST', '/users', body);
}
else if (operation === 'update') {
// ----------------------------------
// user:update
// ----------------------------------
// https://docs.zammad.org/en/latest/api/user.html#update
const id = this.getNodeParameter('id', i);
const body = {};
const updateFields = this.getNodeParameter('updateFields', i);
if (!Object.keys(updateFields).length) {
GenericFunctions_1.throwOnEmptyUpdate.call(this, resource);
}
const { addressUi, customFieldsUi, ...rest } = updateFields;
Object.assign(body, addressUi?.addressDetails);
customFieldsUi?.customFieldPairs.forEach((pair) => {
body[pair.name] = pair.value;
});
Object.assign(body, rest);
responseData = await GenericFunctions_1.zammadApiRequest.call(this, 'PUT', `/users/${id}`, body);
}
else if (operation === 'delete') {
// ----------------------------------
// user:delete
// ----------------------------------
// https://docs.zammad.org/en/latest/api/user.html#delete
const id = this.getNodeParameter('id', i);
await GenericFunctions_1.zammadApiRequest.call(this, 'DELETE', `/users/${id}`);
responseData = { success: true };
}
else if (operation === 'get') {
// ----------------------------------
// user:get
// ----------------------------------
// https://docs.zammad.org/en/latest/api/user.html#show
const id = this.getNodeParameter('id', i);
responseData = await GenericFunctions_1.zammadApiRequest.call(this, 'GET', `/users/${id}`);
}
else if (operation === 'getAll') {
// ----------------------------------
// user:getAll
// ----------------------------------
// https://docs.zammad.org/en/latest/api/user.html#list
// https://docs.zammad.org/en/latest/api/user.html#search
const qs = {};
const { sortUi, ...rest } = this.getNodeParameter('filters', i);
Object.assign(qs, sortUi?.sortDetails);
Object.assign(qs, rest);
qs.query ||= ''; // otherwise triggers 500
const returnAll = this.getNodeParameter('returnAll', i);
const limit = returnAll ? 0 : this.getNodeParameter('limit', i);
responseData = await GenericFunctions_1.zammadApiRequestAllItems
.call(this, 'GET', '/users/search', {}, qs, limit)
.then((response) => {
return response.map((user) => {
const { _preferences, ...data } = user;
return data;
});
});
}
else if (operation === 'getSelf') {
// ----------------------------------
// user:me
// ----------------------------------
// https://docs.zammad.org/en/latest/api/user.html#me-current-user
responseData = await GenericFunctions_1.zammadApiRequest.call(this, 'GET', '/users/me');
}
}
else if (resource === 'organization') {
// **********************************************************************
// organization
// **********************************************************************
if (operation === 'create') {
// ----------------------------------
// organization:create
// ----------------------------------
// https://docs.zammad.org/en/latest/api/organization.html#create
const body = {
name: this.getNodeParameter('name', i),
};
const { customFieldsUi, ...rest } = this.getNodeParameter('additionalFields', i);
customFieldsUi?.customFieldPairs.forEach((pair) => {
body[pair.name] = pair.value;
});
Object.assign(body, rest);
responseData = await GenericFunctions_1.zammadApiRequest.call(this, 'POST', '/organizations', body);
}
else if (operation === 'update') {
// ----------------------------------
// organization:update
// ----------------------------------
// https://docs.zammad.org/en/latest/api/organization.html#update
const id = this.getNodeParameter('id', i);
const body = {};
const updateFields = this.getNodeParameter('updateFields', i);
if (!Object.keys(updateFields).length) {
GenericFunctions_1.throwOnEmptyUpdate.call(this, resource);
}
const { customFieldsUi, ...rest } = updateFields;
customFieldsUi?.customFieldPairs.forEach((pair) => {
body[pair.name] = pair.value;
});
Object.assign(body, rest);
responseData = await GenericFunctions_1.zammadApiRequest.call(this, 'PUT', `/organizations/${id}`, body);
}
else if (operation === 'delete') {
// ----------------------------------
// organization:delete
// ----------------------------------
// https://docs.zammad.org/en/latest/api/organization.html#delete
const id = this.getNodeParameter('id', i);
await GenericFunctions_1.zammadApiRequest.call(this, 'DELETE', `/organizations/${id}`);
responseData = { success: true };
}
else if (operation === 'get') {
// ----------------------------------
// organization:get
// ----------------------------------
// https://docs.zammad.org/en/latest/api/organization.html#show
const id = this.getNodeParameter('id', i);
responseData = await GenericFunctions_1.zammadApiRequest.call(this, 'GET', `/organizations/${id}`);
}
else if (operation === 'getAll') {
// ----------------------------------
// organization:getAll
// ----------------------------------
// https://docs.zammad.org/en/latest/api/organization.html#list
// https://docs.zammad.org/en/latest/api/organization.html#search - returning empty always
const returnAll = this.getNodeParameter('returnAll', i);
const limit = returnAll ? 0 : this.getNodeParameter('limit', i);
responseData = await GenericFunctions_1.zammadApiRequestAllItems.call(this, 'GET', '/organizations', {}, {}, limit);
}
}
else if (resource === 'group') {
// **********************************************************************
// group
// **********************************************************************
if (operation === 'create') {
// ----------------------------------
// group:create
// ----------------------------------
// https://docs.zammad.org/en/latest/api/group.html#create
const body = {
name: this.getNodeParameter('name', i),
};
const { customFieldsUi, ...rest } = this.getNodeParameter('additionalFields', i);
customFieldsUi?.customFieldPairs.forEach((pair) => {
body[pair.name] = pair.value;
});
Object.assign(body, rest);
responseData = await GenericFunctions_1.zammadApiRequest.call(this, 'POST', '/groups', body);
}
else if (operation === 'update') {
// ----------------------------------
// group:update
// ----------------------------------
// https://docs.zammad.org/en/latest/api/group.html#update
const id = this.getNodeParameter('id', i);
const body = {};
const updateFields = this.getNodeParameter('updateFields', i);
if (!Object.keys(updateFields).length) {
GenericFunctions_1.throwOnEmptyUpdate.call(this, resource);
}
const { customFieldsUi, ...rest } = updateFields;
customFieldsUi?.customFieldPairs.forEach((pair) => {
body[pair.name] = pair.value;
});
Object.assign(body, rest);
responseData = await GenericFunctions_1.zammadApiRequest.call(this, 'PUT', `/groups/${id}`, body);
}
else if (operation === 'delete') {
// ----------------------------------
// group:delete
// ----------------------------------
// https://docs.zammad.org/en/latest/api/group.html#delete
const id = this.getNodeParameter('id', i);
await GenericFunctions_1.zammadApiRequest.call(this, 'DELETE', `/groups/${id}`);
responseData = { success: true };
}
else if (operation === 'get') {
// ----------------------------------
// group:get
// ----------------------------------
// https://docs.zammad.org/en/latest/api/group.html#show
const id = this.getNodeParameter('id', i);
responseData = await GenericFunctions_1.zammadApiRequest.call(this, 'GET', `/groups/${id}`);
}
else if (operation === 'getAll') {
// ----------------------------------
// group:getAll
// ----------------------------------
// https://docs.zammad.org/en/latest/api/group.html#list
const returnAll = this.getNodeParameter('returnAll', i);
const limit = returnAll ? 0 : this.getNodeParameter('limit', i);
responseData = await GenericFunctions_1.zammadApiRequestAllItems.call(this, 'GET', '/groups', {}, {}, limit);
}
}
else if (resource === 'ticket') {
// **********************************************************************
// ticket
// **********************************************************************
if (operation === 'create') {
// ----------------------------------
// ticket:create
// ----------------------------------
// https://docs.zammad.org/en/latest/api/ticket/index.html#create
const body = {
article: {},
title: this.getNodeParameter('title', i),
group: this.getNodeParameter('group', i),
customer: this.getNodeParameter('customer', i),
};
const { customFieldsUi, ...additionalFields } = this.getNodeParameter('additionalFields', i);
if (customFieldsUi) {
const customFields = customFieldsUi;
for (const pair of customFields.customFieldPairs) {
const resolvedName = pair.name;
body[resolvedName] = pair.value;
}
}
Object.assign(body, additionalFields);
const article = this.getNodeParameter('article', i);
if (!Object.keys(article).length) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Article is required', { itemIndex: i });
}
const { articleDetails: { visibility, ...rest }, } = article;
body.article = {
...rest,
internal: visibility === 'internal',
};
responseData = await GenericFunctions_1.zammadApiRequest.call(this, 'POST', '/tickets', body);
const { id } = responseData;
responseData.articles = await GenericFunctions_1.zammadApiRequest.call(this, 'GET', `/ticket_articles/by_ticket/${id}`);
}
else if (operation === 'update') {
// ----------------------------------
// ticket:update
// ----------------------------------
// https://docs.zammad.org/en/latest/api/ticket/index.html#update
const id = this.getNodeParameter('id', i);
const body = {};
const updateFields = this.getNodeParameter('updateFields', i);
if (!Object.keys(updateFields).length) {
GenericFunctions_1.throwOnEmptyUpdate.call(this, resource);
}
const { note, customFieldsUi, ...rest } = updateFields;
if (note) {
body.article = {
body: note,
internal: true,
type: 'note',
content_type: 'text/html',
};
}
if (customFieldsUi) {
const customFields = customFieldsUi;
for (const pair of customFields.customFieldPairs) {
const resolvedName = pair.name;
body[resolvedName] = pair.value;
}
}
Object.assign(body, rest);
if (body.pending_time === '') {
delete body.pending_time;
}
responseData = await GenericFunctions_1.zammadApiRequest.call(this, 'PUT', `/tickets/${id}`, body);
}
else if (operation === 'delete') {
// ----------------------------------
// ticket:delete
// ----------------------------------
// https://docs.zammad.org/en/latest/api/ticket/index.html#delete
const id = this.getNodeParameter('id', i);
await GenericFunctions_1.zammadApiRequest.call(this, 'DELETE', `/tickets/${id}`);
responseData = { success: true };
}
else if (operation === 'get') {
// ----------------------------------
// ticket:get
// ----------------------------------
// https://docs.zammad.org/en/latest/api/ticket/index.html#show
const id = this.getNodeParameter('id', i);
responseData = await GenericFunctions_1.zammadApiRequest.call(this, 'GET', `/tickets/${id}`);
responseData.articles = await GenericFunctions_1.zammadApiRequest.call(this, 'GET', `/ticket_articles/by_ticket/${id}`);
}
else if (operation === 'getAll') {
// ----------------------------------
// ticket:getAll
// ----------------------------------
// https://docs.zammad.org/en/latest/api/ticket/index.html#list
// https://docs.zammad.org/en/latest/api/ticket/index.html#search - returning empty always
const returnAll = this.getNodeParameter('returnAll', i);
const limit = returnAll ? 0 : this.getNodeParameter('limit', i);
responseData = await GenericFunctions_1.zammadApiRequestAllItems.call(this, 'GET', '/tickets', {}, {}, limit);
}
}
const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
returnData.push(...executionData);
}
catch (error) {
if (this.continueOnFail()) {
returnData.push({ json: { error: error.message } });
continue;
}
throw error;
}
}
return [returnData];
}
}
exports.Zammad = Zammad;
//# sourceMappingURL=Zammad.node.js.map