n8n_node_librebooking/nodes/LibreBooking/LibreBooking.node.ts

1204 lines
54 KiB
TypeScript

import {
IExecuteFunctions,
INodeExecutionData,
INodeType,
INodeTypeDescription,
IHttpRequestMethods,
NodeApiError,
NodeOperationError,
} from 'n8n-workflow';
interface LibreBookingSession {
sessionToken: string;
userId: number;
sessionExpires: string;
}
/**
* Authentifizierung bei LibreBooking
*/
async function authenticate(
executeFunctions: IExecuteFunctions,
baseUrl: string,
username: string,
password: string,
): Promise<LibreBookingSession> {
try {
const response = await executeFunctions.helpers.httpRequest({
method: 'POST',
url: `${baseUrl}/Web/Services/index.php/Authentication/Authenticate`,
headers: { 'Content-Type': 'application/json' },
body: { username, password },
json: true,
});
if (!response.isAuthenticated) {
throw new NodeOperationError(
executeFunctions.getNode(),
'Authentifizierung fehlgeschlagen. Bitte überprüfen Sie Ihre Credentials.',
);
}
return {
sessionToken: response.sessionToken,
userId: response.userId,
sessionExpires: response.sessionExpires,
};
} catch (error: any) {
throw new NodeApiError(executeFunctions.getNode(), error, {
message: 'Authentifizierung fehlgeschlagen',
description: 'Überprüfen Sie die LibreBooking URL und Ihre Zugangsdaten.',
});
}
}
/**
* Abmeldung von LibreBooking
*/
async function signOut(
executeFunctions: IExecuteFunctions,
baseUrl: string,
session: LibreBookingSession,
): Promise<void> {
try {
await executeFunctions.helpers.httpRequest({
method: 'POST',
url: `${baseUrl}/Web/Services/index.php/Authentication/SignOut`,
headers: { 'Content-Type': 'application/json' },
body: {
userId: session.userId,
sessionToken: session.sessionToken,
},
json: true,
});
} catch (error) {
// Ignoriere SignOut-Fehler
}
}
/**
* API-Request mit Session-Authentifizierung
*/
async function makeApiRequest(
executeFunctions: IExecuteFunctions,
baseUrl: string,
session: LibreBookingSession,
method: IHttpRequestMethods,
endpoint: string,
body?: any,
qs?: any,
): Promise<any> {
const options: any = {
method,
url: `${baseUrl}/Web/Services/index.php${endpoint}`,
headers: {
'Content-Type': 'application/json',
'X-Booked-SessionToken': session.sessionToken,
'X-Booked-UserId': session.userId.toString(),
},
json: true,
};
if (body && Object.keys(body).length > 0) {
options.body = body;
}
if (qs && Object.keys(qs).length > 0) {
options.qs = qs;
}
try {
return await executeFunctions.helpers.httpRequest(options);
} catch (error: any) {
if (error.statusCode === 401) {
throw new NodeApiError(executeFunctions.getNode(), error, {
message: 'Authentifizierung abgelaufen',
description: 'Der Session-Token ist abgelaufen. Bitte erneut ausführen.',
});
} else if (error.statusCode === 403) {
throw new NodeApiError(executeFunctions.getNode(), error, {
message: 'Zugriff verweigert',
description: 'Sie haben keine Berechtigung für diese Operation. Admin-Rechte erforderlich?',
});
} else if (error.statusCode === 404) {
throw new NodeApiError(executeFunctions.getNode(), error, {
message: 'Nicht gefunden',
description: 'Die angeforderte Ressource wurde nicht gefunden.',
});
}
throw new NodeApiError(executeFunctions.getNode(), error, {
message: `API-Fehler: ${error.message}`,
});
}
}
/**
* Hilfsfunktion: String zu Array von Zahlen
*/
function parseIdList(value: string | undefined): number[] {
if (!value || value.trim() === '') return [];
return value.split(',').map(id => parseInt(id.trim(), 10)).filter(id => !isNaN(id));
}
/**
* LibreBooking n8n Node
*
* Vollständige Integration für die LibreBooking API.
* Unterstützt alle wichtigen Ressourcen und Operationen.
*/
export class LibreBooking implements INodeType {
description: INodeTypeDescription = {
displayName: 'LibreBooking',
name: 'libreBooking',
icon: 'file:librebooking.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Verwalten Sie Reservierungen, Ressourcen, Benutzer und mehr mit LibreBooking',
defaults: {
name: 'LibreBooking',
},
inputs: ['main'],
outputs: ['main'],
credentials: [
{
name: 'libreBookingApi',
required: true,
},
],
properties: [
// =====================================================
// RESOURCE SELECTOR
// =====================================================
{
displayName: 'Ressource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Reservierung',
value: 'reservation',
description: 'Reservierungen verwalten',
},
{
name: 'Ressource',
value: 'resource',
description: 'Ressourcen (Räume, Equipment) verwalten',
},
{
name: 'Zeitplan',
value: 'schedule',
description: 'Zeitpläne abrufen',
},
{
name: 'Benutzer',
value: 'user',
description: 'Benutzer verwalten (Admin-Rechte erforderlich)',
},
{
name: 'Konto',
value: 'account',
description: 'Eigenes Konto verwalten',
},
{
name: 'Gruppe',
value: 'group',
description: 'Benutzergruppen verwalten',
},
{
name: 'Zubehör',
value: 'accessory',
description: 'Zubehör abrufen',
},
{
name: 'Attribut',
value: 'attribute',
description: 'Benutzerdefinierte Attribute verwalten',
},
],
default: 'reservation',
},
// =====================================================
// RESERVATION OPERATIONS
// =====================================================
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['reservation'],
},
},
options: [
{ name: 'Erstellen', value: 'create', description: 'Neue Reservierung erstellen', action: 'Reservierung erstellen' },
{ name: 'Abrufen', value: 'get', description: 'Reservierung abrufen', action: 'Reservierung abrufen' },
{ name: 'Alle Abrufen', value: 'getAll', description: 'Alle Reservierungen abrufen', action: 'Alle Reservierungen abrufen' },
{ name: 'Aktualisieren', value: 'update', description: 'Reservierung aktualisieren', action: 'Reservierung aktualisieren' },
{ name: 'Löschen', value: 'delete', description: 'Reservierung löschen', action: 'Reservierung löschen' },
{ name: 'Genehmigen', value: 'approve', description: 'Ausstehende Reservierung genehmigen', action: 'Reservierung genehmigen' },
{ name: 'Check-In', value: 'checkIn', description: 'In Reservierung einchecken', action: 'In Reservierung einchecken' },
{ name: 'Check-Out', value: 'checkOut', description: 'Aus Reservierung auschecken', action: 'Aus Reservierung auschecken' },
],
default: 'getAll',
},
// =====================================================
// RESOURCE OPERATIONS
// =====================================================
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: { show: { resource: ['resource'] } },
options: [
{ name: 'Alle Abrufen', value: 'getAll', description: 'Alle Ressourcen abrufen', action: 'Alle Ressourcen abrufen' },
{ name: 'Abrufen', value: 'get', description: 'Ressource abrufen', action: 'Ressource abrufen' },
{ name: 'Verfügbarkeit Prüfen', value: 'getAvailability', description: 'Verfügbarkeit von Ressourcen prüfen', action: 'Verfügbarkeit prüfen' },
{ name: 'Gruppen Abrufen', value: 'getGroups', description: 'Ressourcen-Gruppen abrufen', action: 'Ressourcen-Gruppen abrufen' },
{ name: 'Typen Abrufen', value: 'getTypes', description: 'Ressourcen-Typen abrufen', action: 'Ressourcen-Typen abrufen' },
{ name: 'Status Abrufen', value: 'getStatuses', description: 'Verfügbare Status abrufen', action: 'Status abrufen' },
{ name: 'Erstellen', value: 'create', description: 'Neue Ressource erstellen (Admin)', action: 'Ressource erstellen' },
{ name: 'Aktualisieren', value: 'update', description: 'Ressource aktualisieren (Admin)', action: 'Ressource aktualisieren' },
{ name: 'Löschen', value: 'delete', description: 'Ressource löschen (Admin)', action: 'Ressource löschen' },
],
default: 'getAll',
},
// =====================================================
// SCHEDULE OPERATIONS
// =====================================================
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: { show: { resource: ['schedule'] } },
options: [
{ name: 'Alle Abrufen', value: 'getAll', description: 'Alle Zeitpläne abrufen', action: 'Alle Zeitpläne abrufen' },
{ name: 'Abrufen', value: 'get', description: 'Zeitplan abrufen', action: 'Zeitplan abrufen' },
{ name: 'Slots Abrufen', value: 'getSlots', description: 'Verfügbare Slots abrufen', action: 'Slots abrufen' },
],
default: 'getAll',
},
// =====================================================
// USER OPERATIONS
// =====================================================
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: { show: { resource: ['user'] } },
options: [
{ name: 'Alle Abrufen', value: 'getAll', description: 'Alle Benutzer abrufen', action: 'Alle Benutzer abrufen' },
{ name: 'Abrufen', value: 'get', description: 'Benutzer abrufen', action: 'Benutzer abrufen' },
{ name: 'Erstellen', value: 'create', description: 'Neuen Benutzer erstellen (Admin)', action: 'Benutzer erstellen' },
{ name: 'Aktualisieren', value: 'update', description: 'Benutzer aktualisieren (Admin)', action: 'Benutzer aktualisieren' },
{ name: 'Passwort Ändern', value: 'updatePassword', description: 'Benutzer-Passwort ändern (Admin)', action: 'Passwort ändern' },
{ name: 'Löschen', value: 'delete', description: 'Benutzer löschen (Admin)', action: 'Benutzer löschen' },
],
default: 'getAll',
},
// =====================================================
// ACCOUNT OPERATIONS
// =====================================================
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: { show: { resource: ['account'] } },
options: [
{ name: 'Abrufen', value: 'get', description: 'Eigene Kontoinformationen abrufen', action: 'Konto abrufen' },
{ name: 'Erstellen', value: 'create', description: 'Neues Konto erstellen (Registrierung)', action: 'Konto erstellen' },
{ name: 'Aktualisieren', value: 'update', description: 'Eigenes Konto aktualisieren', action: 'Konto aktualisieren' },
{ name: 'Passwort Ändern', value: 'updatePassword', description: 'Eigenes Passwort ändern', action: 'Passwort ändern' },
],
default: 'get',
},
// =====================================================
// GROUP OPERATIONS
// =====================================================
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: { show: { resource: ['group'] } },
options: [
{ name: 'Alle Abrufen', value: 'getAll', description: 'Alle Gruppen abrufen', action: 'Alle Gruppen abrufen' },
{ name: 'Abrufen', value: 'get', description: 'Gruppe abrufen', action: 'Gruppe abrufen' },
{ name: 'Erstellen', value: 'create', description: 'Neue Gruppe erstellen (Admin)', action: 'Gruppe erstellen' },
{ name: 'Aktualisieren', value: 'update', description: 'Gruppe aktualisieren (Admin)', action: 'Gruppe aktualisieren' },
{ name: 'Löschen', value: 'delete', description: 'Gruppe löschen (Admin)', action: 'Gruppe löschen' },
{ name: 'Rollen Ändern', value: 'changeRoles', description: 'Gruppenrollen ändern (Admin)', action: 'Rollen ändern' },
{ name: 'Berechtigungen Ändern', value: 'changePermissions', description: 'Gruppenberechtigungen ändern (Admin)', action: 'Berechtigungen ändern' },
{ name: 'Benutzer Ändern', value: 'changeUsers', description: 'Gruppenbenutzer ändern (Admin)', action: 'Benutzer ändern' },
],
default: 'getAll',
},
// =====================================================
// ACCESSORY OPERATIONS
// =====================================================
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: { show: { resource: ['accessory'] } },
options: [
{ name: 'Alle Abrufen', value: 'getAll', description: 'Alle Zubehörteile abrufen', action: 'Alle Zubehörteile abrufen' },
{ name: 'Abrufen', value: 'get', description: 'Zubehörteil abrufen', action: 'Zubehörteil abrufen' },
],
default: 'getAll',
},
// =====================================================
// ATTRIBUTE OPERATIONS
// =====================================================
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: { show: { resource: ['attribute'] } },
options: [
{ name: 'Abrufen', value: 'get', description: 'Attribut abrufen', action: 'Attribut abrufen' },
{ name: 'Nach Kategorie Abrufen', value: 'getByCategory', description: 'Attribute einer Kategorie abrufen', action: 'Attribute nach Kategorie abrufen' },
{ name: 'Erstellen', value: 'create', description: 'Neues Attribut erstellen (Admin)', action: 'Attribut erstellen' },
{ name: 'Aktualisieren', value: 'update', description: 'Attribut aktualisieren (Admin)', action: 'Attribut aktualisieren' },
{ name: 'Löschen', value: 'delete', description: 'Attribut löschen (Admin)', action: 'Attribut löschen' },
],
default: 'getByCategory',
},
// =====================================================
// RESERVATION PARAMETERS
// =====================================================
{
displayName: 'Referenznummer',
name: 'referenceNumber',
type: 'string',
required: true,
displayOptions: { show: { resource: ['reservation'], operation: ['get', 'update', 'delete', 'approve', 'checkIn', 'checkOut'] } },
default: '',
description: 'Die eindeutige Referenznummer der Reservierung',
},
{
displayName: 'Ressourcen-ID',
name: 'resourceId',
type: 'number',
required: true,
displayOptions: { show: { resource: ['reservation'], operation: ['create'] } },
default: 1,
description: 'Die ID der zu reservierenden Ressource',
},
{
displayName: 'Startzeit',
name: 'startDateTime',
type: 'dateTime',
required: true,
displayOptions: { show: { resource: ['reservation'], operation: ['create', 'update'] } },
default: '',
description: 'Startzeitpunkt der Reservierung (ISO 8601 Format)',
},
{
displayName: 'Endzeit',
name: 'endDateTime',
type: 'dateTime',
required: true,
displayOptions: { show: { resource: ['reservation'], operation: ['create', 'update'] } },
default: '',
description: 'Endzeitpunkt der Reservierung (ISO 8601 Format)',
},
{
displayName: 'Titel',
name: 'title',
type: 'string',
displayOptions: { show: { resource: ['reservation'], operation: ['create', 'update'] } },
default: '',
description: 'Titel der Reservierung',
},
{
displayName: 'Aktualisierungsbereich',
name: 'updateScope',
type: 'options',
displayOptions: { show: { resource: ['reservation'], operation: ['update', 'delete'] } },
options: [
{ name: 'Nur Diese', value: 'this', description: 'Nur diese Instanz ändern' },
{ name: 'Zukünftige', value: 'future', description: 'Diese und alle zukünftigen Instanzen ändern' },
{ name: 'Alle', value: 'full', description: 'Alle Instanzen der Serie ändern' },
],
default: 'this',
},
{
displayName: 'Zusätzliche Felder',
name: 'additionalFields',
type: 'collection',
placeholder: 'Feld hinzufügen',
default: {},
displayOptions: { show: { resource: ['reservation'], operation: ['create', 'update'] } },
options: [
{ displayName: 'Beschreibung', name: 'description', type: 'string', default: '' },
{ displayName: 'Benutzer-ID', name: 'userId', type: 'number', default: '' },
{ displayName: 'Zusätzliche Ressourcen', name: 'resources', type: 'string', default: '', description: 'Komma-getrennte Liste' },
{ displayName: 'Teilnehmer', name: 'participants', type: 'string', default: '', description: 'Komma-getrennte Benutzer-IDs' },
{ displayName: 'Eingeladene', name: 'invitees', type: 'string', default: '', description: 'Komma-getrennte Benutzer-IDs' },
{ displayName: 'Teilnahme Erlauben', name: 'allowParticipation', type: 'boolean', default: true },
{ displayName: 'Nutzungsbedingungen Akzeptiert', name: 'termsAccepted', type: 'boolean', default: true },
],
},
{
displayName: 'Filter',
name: 'filters',
type: 'collection',
placeholder: 'Filter hinzufügen',
default: {},
displayOptions: { show: { resource: ['reservation'], operation: ['getAll'] } },
options: [
{ displayName: 'Benutzer-ID', name: 'userId', type: 'number', default: '' },
{ displayName: 'Ressourcen-ID', name: 'resourceId', type: 'number', default: '' },
{ displayName: 'Zeitplan-ID', name: 'scheduleId', type: 'number', default: '' },
{ displayName: 'Startzeit', name: 'startDateTime', type: 'dateTime', default: '' },
{ displayName: 'Endzeit', name: 'endDateTime', type: 'dateTime', default: '' },
],
},
// =====================================================
// RESOURCE PARAMETERS
// =====================================================
{
displayName: 'Ressourcen-ID',
name: 'resourceIdParam',
type: 'number',
required: true,
displayOptions: { show: { resource: ['resource'], operation: ['get', 'update', 'delete'] } },
default: 1,
},
{
displayName: 'Ressourcen-ID (Optional)',
name: 'resourceIdOptional',
type: 'number',
displayOptions: { show: { resource: ['resource'], operation: ['getAvailability'] } },
default: '',
},
{
displayName: 'Datum/Zeit',
name: 'availabilityDateTime',
type: 'dateTime',
displayOptions: { show: { resource: ['resource'], operation: ['getAvailability'] } },
default: '',
},
{
displayName: 'Ressourcen-Name',
name: 'resourceName',
type: 'string',
required: true,
displayOptions: { show: { resource: ['resource'], operation: ['create', 'update'] } },
default: '',
},
{
displayName: 'Zeitplan-ID',
name: 'scheduleIdForResource',
type: 'number',
required: true,
displayOptions: { show: { resource: ['resource'], operation: ['create'] } },
default: 1,
},
{
displayName: 'Ressourcen-Optionen',
name: 'resourceOptions',
type: 'collection',
placeholder: 'Option hinzufügen',
default: {},
displayOptions: { show: { resource: ['resource'], operation: ['create', 'update'] } },
options: [
{ displayName: 'Standort', name: 'location', type: 'string', default: '' },
{ displayName: 'Kontakt', name: 'contact', type: 'string', default: '' },
{ displayName: 'Beschreibung', name: 'description', type: 'string', default: '' },
{ displayName: 'Notizen', name: 'notes', type: 'string', default: '' },
{ displayName: 'Max. Teilnehmer', name: 'maxParticipants', type: 'number', default: 0 },
{ displayName: 'Genehmigung Erforderlich', name: 'requiresApproval', type: 'boolean', default: false },
{ displayName: 'Mehrtägig Erlauben', name: 'allowMultiday', type: 'boolean', default: false },
{ displayName: 'Check-In Erforderlich', name: 'requiresCheckIn', type: 'boolean', default: false },
{ displayName: 'Auto-Release Minuten', name: 'autoReleaseMinutes', type: 'number', default: 0 },
{ displayName: 'Farbe', name: 'color', type: 'string', default: '' },
{ displayName: 'Status-ID', name: 'statusId', type: 'options', options: [{ name: 'Versteckt', value: 0 }, { name: 'Verfügbar', value: 1 }, { name: 'Nicht Verfügbar', value: 2 }], default: 1 },
],
},
// =====================================================
// SCHEDULE PARAMETERS
// =====================================================
{
displayName: 'Zeitplan-ID',
name: 'scheduleId',
type: 'number',
required: true,
displayOptions: { show: { resource: ['schedule'], operation: ['get', 'getSlots'] } },
default: 1,
},
{
displayName: 'Slots-Filter',
name: 'slotsFilters',
type: 'collection',
placeholder: 'Filter hinzufügen',
default: {},
displayOptions: { show: { resource: ['schedule'], operation: ['getSlots'] } },
options: [
{ displayName: 'Ressourcen-ID', name: 'resourceId', type: 'number', default: '' },
{ displayName: 'Startzeit', name: 'startDateTime', type: 'dateTime', default: '' },
{ displayName: 'Endzeit', name: 'endDateTime', type: 'dateTime', default: '' },
],
},
// =====================================================
// USER PARAMETERS
// =====================================================
{
displayName: 'Benutzer-ID',
name: 'userId',
type: 'number',
required: true,
displayOptions: { show: { resource: ['user'], operation: ['get', 'update', 'updatePassword', 'delete'] } },
default: 1,
},
{
displayName: 'E-Mail',
name: 'emailAddress',
type: 'string',
required: true,
displayOptions: { show: { resource: ['user'], operation: ['create'] } },
default: '',
},
{
displayName: 'Benutzername',
name: 'userName',
type: 'string',
required: true,
displayOptions: { show: { resource: ['user'], operation: ['create'] } },
default: '',
},
{
displayName: 'Passwort',
name: 'password',
type: 'string',
typeOptions: { password: true },
required: true,
displayOptions: { show: { resource: ['user'], operation: ['create', 'updatePassword'] } },
default: '',
},
{
displayName: 'Vorname',
name: 'firstName',
type: 'string',
required: true,
displayOptions: { show: { resource: ['user'], operation: ['create', 'update'] } },
default: '',
},
{
displayName: 'Nachname',
name: 'lastName',
type: 'string',
required: true,
displayOptions: { show: { resource: ['user'], operation: ['create', 'update'] } },
default: '',
},
{
displayName: 'Benutzer-Filter',
name: 'userFilters',
type: 'collection',
placeholder: 'Filter hinzufügen',
default: {},
displayOptions: { show: { resource: ['user'], operation: ['getAll'] } },
options: [
{ displayName: 'Benutzername', name: 'username', type: 'string', default: '' },
{ displayName: 'E-Mail', name: 'email', type: 'string', default: '' },
{ displayName: 'Vorname', name: 'firstName', type: 'string', default: '' },
{ displayName: 'Nachname', name: 'lastName', type: 'string', default: '' },
{ displayName: 'Organisation', name: 'organization', type: 'string', default: '' },
],
},
{
displayName: 'Benutzer-Optionen',
name: 'userOptions',
type: 'collection',
placeholder: 'Option hinzufügen',
default: {},
displayOptions: { show: { resource: ['user'], operation: ['create', 'update'] } },
options: [
{ displayName: 'Zeitzone', name: 'timezone', type: 'string', default: 'Europe/Berlin' },
{ displayName: 'Sprache', name: 'language', type: 'string', default: 'de_de' },
{ displayName: 'Telefon', name: 'phone', type: 'string', default: '' },
{ displayName: 'Organisation', name: 'organization', type: 'string', default: '' },
{ displayName: 'Position', name: 'position', type: 'string', default: '' },
{ displayName: 'Gruppen', name: 'groups', type: 'string', default: '', description: 'Komma-getrennte Gruppen-IDs' },
],
},
// =====================================================
// ACCOUNT PARAMETERS
// =====================================================
{
displayName: 'Benutzer-ID',
name: 'accountUserId',
type: 'number',
required: true,
displayOptions: { show: { resource: ['account'], operation: ['get', 'update', 'updatePassword'] } },
default: '',
},
{
displayName: 'Account-Daten',
name: 'accountData',
type: 'collection',
placeholder: 'Feld hinzufügen',
default: {},
displayOptions: { show: { resource: ['account'], operation: ['create', 'update'] } },
options: [
{ displayName: 'E-Mail', name: 'emailAddress', type: 'string', default: '' },
{ displayName: 'Benutzername', name: 'userName', type: 'string', default: '' },
{ displayName: 'Passwort', name: 'password', type: 'string', typeOptions: { password: true }, default: '' },
{ displayName: 'Vorname', name: 'firstName', type: 'string', default: '' },
{ displayName: 'Nachname', name: 'lastName', type: 'string', default: '' },
{ displayName: 'Zeitzone', name: 'timezone', type: 'string', default: 'Europe/Berlin' },
{ displayName: 'Sprache', name: 'language', type: 'string', default: 'de_de' },
{ displayName: 'Telefon', name: 'phone', type: 'string', default: '' },
{ displayName: 'Organisation', name: 'organization', type: 'string', default: '' },
{ displayName: 'Position', name: 'position', type: 'string', default: '' },
{ displayName: 'AGB Akzeptiert', name: 'acceptTermsOfService', type: 'boolean', default: true },
],
},
{
displayName: 'Passwort-Änderung',
name: 'passwordChange',
type: 'fixedCollection',
default: {},
displayOptions: { show: { resource: ['account'], operation: ['updatePassword'] } },
options: [
{
name: 'passwords',
displayName: 'Passwörter',
values: [
{ displayName: 'Aktuelles Passwort', name: 'currentPassword', type: 'string', typeOptions: { password: true }, default: '' },
{ displayName: 'Neues Passwort', name: 'newPassword', type: 'string', typeOptions: { password: true }, default: '' },
],
},
],
},
// =====================================================
// GROUP PARAMETERS
// =====================================================
{
displayName: 'Gruppen-ID',
name: 'groupId',
type: 'number',
required: true,
displayOptions: { show: { resource: ['group'], operation: ['get', 'update', 'delete', 'changeRoles', 'changePermissions', 'changeUsers'] } },
default: 1,
},
{
displayName: 'Gruppen-Name',
name: 'groupName',
type: 'string',
required: true,
displayOptions: { show: { resource: ['group'], operation: ['create', 'update'] } },
default: '',
},
{
displayName: 'Standard-Gruppe',
name: 'isDefault',
type: 'boolean',
displayOptions: { show: { resource: ['group'], operation: ['create', 'update'] } },
default: false,
},
{
displayName: 'Rollen-IDs',
name: 'roleIds',
type: 'string',
displayOptions: { show: { resource: ['group'], operation: ['changeRoles'] } },
default: '',
description: '1=Gruppenadmin, 2=App-Admin, 3=Ressourcen-Admin, 4=Zeitplan-Admin',
},
{
displayName: 'Ressourcen-IDs',
name: 'permissionResourceIds',
type: 'string',
displayOptions: { show: { resource: ['group'], operation: ['changePermissions'] } },
default: '',
},
{
displayName: 'Benutzer-IDs',
name: 'groupUserIds',
type: 'string',
displayOptions: { show: { resource: ['group'], operation: ['changeUsers'] } },
default: '',
},
// =====================================================
// ACCESSORY PARAMETERS
// =====================================================
{
displayName: 'Zubehör-ID',
name: 'accessoryId',
type: 'number',
required: true,
displayOptions: { show: { resource: ['accessory'], operation: ['get'] } },
default: 1,
},
// =====================================================
// ATTRIBUTE PARAMETERS
// =====================================================
{
displayName: 'Attribut-ID',
name: 'attributeId',
type: 'number',
required: true,
displayOptions: { show: { resource: ['attribute'], operation: ['get', 'update', 'delete'] } },
default: 1,
},
{
displayName: 'Kategorie-ID',
name: 'categoryId',
type: 'options',
required: true,
displayOptions: { show: { resource: ['attribute'], operation: ['getByCategory', 'create'] } },
options: [
{ name: 'Reservierung', value: 1 },
{ name: 'Benutzer', value: 2 },
{ name: 'Ressource', value: 4 },
{ name: 'Ressourcen-Typ', value: 5 },
],
default: 1,
},
{
displayName: 'Attribut-Label',
name: 'attributeLabel',
type: 'string',
required: true,
displayOptions: { show: { resource: ['attribute'], operation: ['create', 'update'] } },
default: '',
},
{
displayName: 'Attribut-Typ',
name: 'attributeType',
type: 'options',
required: true,
displayOptions: { show: { resource: ['attribute'], operation: ['create', 'update'] } },
options: [
{ name: 'Einzeilig', value: 1 },
{ name: 'Mehrzeilig', value: 2 },
{ name: 'Auswahlliste', value: 3 },
{ name: 'Checkbox', value: 4 },
{ name: 'Datum/Zeit', value: 5 },
],
default: 1,
},
{
displayName: 'Attribut-Optionen',
name: 'attributeOptions',
type: 'collection',
placeholder: 'Option hinzufügen',
default: {},
displayOptions: { show: { resource: ['attribute'], operation: ['create', 'update'] } },
options: [
{ displayName: 'Erforderlich', name: 'required', type: 'boolean', default: false },
{ displayName: 'Nur Admin', name: 'adminOnly', type: 'boolean', default: false },
{ displayName: 'Privat', name: 'isPrivate', type: 'boolean', default: false },
{ displayName: 'Sortierung', name: 'sortOrder', type: 'number', default: 0 },
{ displayName: 'Regex-Validierung', name: 'regex', type: 'string', default: '' },
{ displayName: 'Mögliche Werte', name: 'possibleValues', type: 'string', default: '', description: 'Komma-getrennt' },
],
},
],
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData();
const returnData: INodeExecutionData[] = [];
const credentials = await this.getCredentials('libreBookingApi');
const baseUrl = (credentials.url as string).replace(/\/$/, '');
const username = credentials.username as string;
const pw = credentials.password as string;
const session = await authenticate(this, baseUrl, username, pw);
try {
for (let i = 0; i < items.length; i++) {
try {
const resource = this.getNodeParameter('resource', i) as string;
const operation = this.getNodeParameter('operation', i) as string;
let responseData: any;
// RESERVATION
if (resource === 'reservation') {
if (operation === 'getAll') {
const filters = this.getNodeParameter('filters', i, {}) as any;
const qs: any = {};
if (filters.userId) qs.userId = filters.userId;
if (filters.resourceId) qs.resourceId = filters.resourceId;
if (filters.scheduleId) qs.scheduleId = filters.scheduleId;
if (filters.startDateTime) qs.startDateTime = filters.startDateTime;
if (filters.endDateTime) qs.endDateTime = filters.endDateTime;
responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Reservations/', undefined, qs);
} else if (operation === 'get') {
const referenceNumber = this.getNodeParameter('referenceNumber', i) as string;
responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Reservations/${referenceNumber}`);
} else if (operation === 'create') {
const resourceId = this.getNodeParameter('resourceId', i) as number;
const startDateTime = this.getNodeParameter('startDateTime', i) as string;
const endDateTime = this.getNodeParameter('endDateTime', i) as string;
const title = this.getNodeParameter('title', i, '') as string;
const additionalFields = this.getNodeParameter('additionalFields', i, {}) as any;
const body: any = { resourceId, startDateTime: new Date(startDateTime).toISOString(), endDateTime: new Date(endDateTime).toISOString() };
if (title) body.title = title;
if (additionalFields.description) body.description = additionalFields.description;
if (additionalFields.userId) body.userId = additionalFields.userId;
if (additionalFields.resources) body.resources = parseIdList(additionalFields.resources);
if (additionalFields.participants) body.participants = parseIdList(additionalFields.participants);
if (additionalFields.invitees) body.invitees = parseIdList(additionalFields.invitees);
if (additionalFields.allowParticipation !== undefined) body.allowParticipation = additionalFields.allowParticipation;
if (additionalFields.termsAccepted !== undefined) body.termsAccepted = additionalFields.termsAccepted;
responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Reservations/', body);
} else if (operation === 'update') {
const referenceNumber = this.getNodeParameter('referenceNumber', i) as string;
const startDateTime = this.getNodeParameter('startDateTime', i) as string;
const endDateTime = this.getNodeParameter('endDateTime', i) as string;
const title = this.getNodeParameter('title', i, '') as string;
const updateScope = this.getNodeParameter('updateScope', i, 'this') as string;
const additionalFields = this.getNodeParameter('additionalFields', i, {}) as any;
const body: any = { startDateTime: new Date(startDateTime).toISOString(), endDateTime: new Date(endDateTime).toISOString() };
if (title) body.title = title;
if (additionalFields.description) body.description = additionalFields.description;
if (additionalFields.resourceId) body.resourceId = additionalFields.resourceId;
if (additionalFields.userId) body.userId = additionalFields.userId;
if (additionalFields.resources) body.resources = parseIdList(additionalFields.resources);
if (additionalFields.participants) body.participants = parseIdList(additionalFields.participants);
if (additionalFields.invitees) body.invitees = parseIdList(additionalFields.invitees);
responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Reservations/${referenceNumber}?updateScope=${updateScope}`, body);
} else if (operation === 'delete') {
const referenceNumber = this.getNodeParameter('referenceNumber', i) as string;
const updateScope = this.getNodeParameter('updateScope', i, 'this') as string;
responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Reservations/${referenceNumber}?updateScope=${updateScope}`);
} else if (operation === 'approve') {
const referenceNumber = this.getNodeParameter('referenceNumber', i) as string;
responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Reservations/${referenceNumber}/Approval`);
} else if (operation === 'checkIn') {
const referenceNumber = this.getNodeParameter('referenceNumber', i) as string;
responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Reservations/${referenceNumber}/CheckIn`);
} else if (operation === 'checkOut') {
const referenceNumber = this.getNodeParameter('referenceNumber', i) as string;
responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Reservations/${referenceNumber}/CheckOut`);
}
}
// RESOURCE
else if (resource === 'resource') {
if (operation === 'getAll') {
responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Resources/');
} else if (operation === 'get') {
const resourceIdParam = this.getNodeParameter('resourceIdParam', i) as number;
responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Resources/${resourceIdParam}`);
} else if (operation === 'getAvailability') {
const resourceIdOptional = this.getNodeParameter('resourceIdOptional', i, '') as number | '';
const availabilityDateTime = this.getNodeParameter('availabilityDateTime', i, '') as string;
let endpoint = '/Resources/Availability';
if (resourceIdOptional) endpoint = `/Resources/${resourceIdOptional}/Availability`;
const qs: any = {};
if (availabilityDateTime) qs.dateTime = new Date(availabilityDateTime).toISOString();
responseData = await makeApiRequest(this, baseUrl, session, 'GET', endpoint, undefined, qs);
} else if (operation === 'getGroups') {
responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Resources/Groups');
} else if (operation === 'getTypes') {
responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Resources/Types');
} else if (operation === 'getStatuses') {
responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Resources/Status');
} else if (operation === 'create') {
const resourceName = this.getNodeParameter('resourceName', i) as string;
const scheduleIdForResource = this.getNodeParameter('scheduleIdForResource', i) as number;
const resourceOptions = this.getNodeParameter('resourceOptions', i, {}) as any;
const body: any = { name: resourceName, scheduleId: scheduleIdForResource };
if (resourceOptions.location) body.location = resourceOptions.location;
if (resourceOptions.contact) body.contact = resourceOptions.contact;
if (resourceOptions.description) body.description = resourceOptions.description;
if (resourceOptions.notes) body.notes = resourceOptions.notes;
if (resourceOptions.maxParticipants) body.maxParticipants = resourceOptions.maxParticipants;
if (resourceOptions.requiresApproval !== undefined) body.requiresApproval = resourceOptions.requiresApproval;
if (resourceOptions.allowMultiday !== undefined) body.allowMultiday = resourceOptions.allowMultiday;
if (resourceOptions.requiresCheckIn !== undefined) body.requiresCheckIn = resourceOptions.requiresCheckIn;
if (resourceOptions.autoReleaseMinutes) body.autoReleaseMinutes = resourceOptions.autoReleaseMinutes;
if (resourceOptions.color) body.color = resourceOptions.color;
if (resourceOptions.statusId !== undefined) body.statusId = resourceOptions.statusId;
responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Resources/', body);
} else if (operation === 'update') {
const resourceIdParam = this.getNodeParameter('resourceIdParam', i) as number;
const resourceName = this.getNodeParameter('resourceName', i) as string;
const resourceOptions = this.getNodeParameter('resourceOptions', i, {}) as any;
const body: any = { name: resourceName };
if (resourceOptions.location) body.location = resourceOptions.location;
if (resourceOptions.contact) body.contact = resourceOptions.contact;
if (resourceOptions.description) body.description = resourceOptions.description;
if (resourceOptions.notes) body.notes = resourceOptions.notes;
if (resourceOptions.maxParticipants) body.maxParticipants = resourceOptions.maxParticipants;
if (resourceOptions.requiresApproval !== undefined) body.requiresApproval = resourceOptions.requiresApproval;
if (resourceOptions.allowMultiday !== undefined) body.allowMultiday = resourceOptions.allowMultiday;
if (resourceOptions.requiresCheckIn !== undefined) body.requiresCheckIn = resourceOptions.requiresCheckIn;
if (resourceOptions.autoReleaseMinutes) body.autoReleaseMinutes = resourceOptions.autoReleaseMinutes;
if (resourceOptions.color) body.color = resourceOptions.color;
if (resourceOptions.statusId !== undefined) body.statusId = resourceOptions.statusId;
responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Resources/${resourceIdParam}`, body);
} else if (operation === 'delete') {
const resourceIdParam = this.getNodeParameter('resourceIdParam', i) as number;
responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Resources/${resourceIdParam}`);
}
}
// SCHEDULE
else if (resource === 'schedule') {
if (operation === 'getAll') {
responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Schedules/');
} else if (operation === 'get') {
const scheduleId = this.getNodeParameter('scheduleId', i) as number;
responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Schedules/${scheduleId}`);
} else if (operation === 'getSlots') {
const scheduleId = this.getNodeParameter('scheduleId', i) as number;
const slotsFilters = this.getNodeParameter('slotsFilters', i, {}) as any;
const qs: any = {};
if (slotsFilters.resourceId) qs.resourceId = slotsFilters.resourceId;
if (slotsFilters.startDateTime) qs.startDateTime = new Date(slotsFilters.startDateTime).toISOString();
if (slotsFilters.endDateTime) qs.endDateTime = new Date(slotsFilters.endDateTime).toISOString();
responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Schedules/${scheduleId}/Slots`, undefined, qs);
}
}
// USER
else if (resource === 'user') {
if (operation === 'getAll') {
const userFilters = this.getNodeParameter('userFilters', i, {}) as any;
const qs: any = {};
if (userFilters.username) qs.username = userFilters.username;
if (userFilters.email) qs.email = userFilters.email;
if (userFilters.firstName) qs.firstName = userFilters.firstName;
if (userFilters.lastName) qs.lastName = userFilters.lastName;
if (userFilters.organization) qs.organization = userFilters.organization;
responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Users/', undefined, qs);
} else if (operation === 'get') {
const userId = this.getNodeParameter('userId', i) as number;
responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Users/${userId}`);
} else if (operation === 'create') {
const emailAddress = this.getNodeParameter('emailAddress', i) as string;
const userName = this.getNodeParameter('userName', i) as string;
const pw = this.getNodeParameter('password', i) as string;
const firstName = this.getNodeParameter('firstName', i) as string;
const lastName = this.getNodeParameter('lastName', i) as string;
const userOptions = this.getNodeParameter('userOptions', i, {}) as any;
const body: any = { emailAddress, userName, password: pw, firstName, lastName };
if (userOptions.timezone) body.timezone = userOptions.timezone;
if (userOptions.language) body.language = userOptions.language;
if (userOptions.phone) body.phone = userOptions.phone;
if (userOptions.organization) body.organization = userOptions.organization;
if (userOptions.position) body.position = userOptions.position;
if (userOptions.groups) body.groups = parseIdList(userOptions.groups);
responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Users/', body);
} else if (operation === 'update') {
const userId = this.getNodeParameter('userId', i) as number;
const firstName = this.getNodeParameter('firstName', i) as string;
const lastName = this.getNodeParameter('lastName', i) as string;
const userOptions = this.getNodeParameter('userOptions', i, {}) as any;
const body: any = { firstName, lastName };
if (userOptions.timezone) body.timezone = userOptions.timezone;
if (userOptions.language) body.language = userOptions.language;
if (userOptions.phone) body.phone = userOptions.phone;
if (userOptions.organization) body.organization = userOptions.organization;
if (userOptions.position) body.position = userOptions.position;
if (userOptions.groups) body.groups = parseIdList(userOptions.groups);
responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Users/${userId}`, body);
} else if (operation === 'updatePassword') {
const userId = this.getNodeParameter('userId', i) as number;
const pw = this.getNodeParameter('password', i) as string;
responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Users/${userId}/Password`, { password: pw });
} else if (operation === 'delete') {
const userId = this.getNodeParameter('userId', i) as number;
responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Users/${userId}`);
}
}
// ACCOUNT
else if (resource === 'account') {
if (operation === 'get') {
const accountUserId = this.getNodeParameter('accountUserId', i) as number;
responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Accounts/${accountUserId}`);
} else if (operation === 'create') {
const accountData = this.getNodeParameter('accountData', i, {}) as any;
const body: any = {};
if (accountData.emailAddress) body.emailAddress = accountData.emailAddress;
if (accountData.userName) body.userName = accountData.userName;
if (accountData.password) body.password = accountData.password;
if (accountData.firstName) body.firstName = accountData.firstName;
if (accountData.lastName) body.lastName = accountData.lastName;
if (accountData.timezone) body.timezone = accountData.timezone;
if (accountData.language) body.language = accountData.language;
if (accountData.phone) body.phone = accountData.phone;
if (accountData.organization) body.organization = accountData.organization;
if (accountData.position) body.position = accountData.position;
if (accountData.acceptTermsOfService !== undefined) body.acceptTermsOfService = accountData.acceptTermsOfService;
responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Accounts/', body);
} else if (operation === 'update') {
const accountUserId = this.getNodeParameter('accountUserId', i) as number;
const accountData = this.getNodeParameter('accountData', i, {}) as any;
const body: any = {};
if (accountData.emailAddress) body.emailAddress = accountData.emailAddress;
if (accountData.userName) body.userName = accountData.userName;
if (accountData.firstName) body.firstName = accountData.firstName;
if (accountData.lastName) body.lastName = accountData.lastName;
if (accountData.timezone) body.timezone = accountData.timezone;
if (accountData.language) body.language = accountData.language;
if (accountData.phone) body.phone = accountData.phone;
if (accountData.organization) body.organization = accountData.organization;
if (accountData.position) body.position = accountData.position;
responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Accounts/${accountUserId}`, body);
} else if (operation === 'updatePassword') {
const accountUserId = this.getNodeParameter('accountUserId', i) as number;
const passwordChange = this.getNodeParameter('passwordChange', i, {}) as any;
const passwords = passwordChange.passwords || {};
responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Accounts/${accountUserId}/Password`, {
currentPassword: passwords.currentPassword,
newPassword: passwords.newPassword,
});
}
}
// GROUP
else if (resource === 'group') {
if (operation === 'getAll') {
responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Groups/');
} else if (operation === 'get') {
const groupId = this.getNodeParameter('groupId', i) as number;
responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Groups/${groupId}`);
} else if (operation === 'create') {
const groupName = this.getNodeParameter('groupName', i) as string;
const isDefault = this.getNodeParameter('isDefault', i, false) as boolean;
responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Groups/', { name: groupName, isDefault });
} else if (operation === 'update') {
const groupId = this.getNodeParameter('groupId', i) as number;
const groupName = this.getNodeParameter('groupName', i) as string;
const isDefault = this.getNodeParameter('isDefault', i, false) as boolean;
responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Groups/${groupId}`, { name: groupName, isDefault });
} else if (operation === 'delete') {
const groupId = this.getNodeParameter('groupId', i) as number;
responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Groups/${groupId}`);
} else if (operation === 'changeRoles') {
const groupId = this.getNodeParameter('groupId', i) as number;
const roleIds = this.getNodeParameter('roleIds', i, '') as string;
responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Groups/${groupId}/Roles`, { roleIds: parseIdList(roleIds) });
} else if (operation === 'changePermissions') {
const groupId = this.getNodeParameter('groupId', i) as number;
const permissionResourceIds = this.getNodeParameter('permissionResourceIds', i, '') as string;
responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Groups/${groupId}/Permissions`, { resourceIds: parseIdList(permissionResourceIds) });
} else if (operation === 'changeUsers') {
const groupId = this.getNodeParameter('groupId', i) as number;
const groupUserIds = this.getNodeParameter('groupUserIds', i, '') as string;
responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Groups/${groupId}/Users`, { userIds: parseIdList(groupUserIds) });
}
}
// ACCESSORY
else if (resource === 'accessory') {
if (operation === 'getAll') {
responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Accessories/');
} else if (operation === 'get') {
const accessoryId = this.getNodeParameter('accessoryId', i) as number;
responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Accessories/${accessoryId}`);
}
}
// ATTRIBUTE
else if (resource === 'attribute') {
if (operation === 'get') {
const attributeId = this.getNodeParameter('attributeId', i) as number;
responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Attributes/${attributeId}`);
} else if (operation === 'getByCategory') {
const categoryId = this.getNodeParameter('categoryId', i) as number;
responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Attributes/Category/${categoryId}`);
} else if (operation === 'create') {
const attributeLabel = this.getNodeParameter('attributeLabel', i) as string;
const attributeType = this.getNodeParameter('attributeType', i) as number;
const categoryId = this.getNodeParameter('categoryId', i) as number;
const attributeOptions = this.getNodeParameter('attributeOptions', i, {}) as any;
const body: any = { label: attributeLabel, type: attributeType, categoryId };
if (attributeOptions.required !== undefined) body.required = attributeOptions.required;
if (attributeOptions.adminOnly !== undefined) body.adminOnly = attributeOptions.adminOnly;
if (attributeOptions.isPrivate !== undefined) body.isPrivate = attributeOptions.isPrivate;
if (attributeOptions.sortOrder !== undefined) body.sortOrder = attributeOptions.sortOrder;
if (attributeOptions.regex) body.regex = attributeOptions.regex;
if (attributeOptions.possibleValues) body.possibleValues = attributeOptions.possibleValues.split(',').map((v: string) => v.trim());
responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Attributes/', body);
} else if (operation === 'update') {
const attributeId = this.getNodeParameter('attributeId', i) as number;
const attributeLabel = this.getNodeParameter('attributeLabel', i) as string;
const attributeType = this.getNodeParameter('attributeType', i) as number;
const attributeOptions = this.getNodeParameter('attributeOptions', i, {}) as any;
const body: any = { label: attributeLabel, type: attributeType };
if (attributeOptions.required !== undefined) body.required = attributeOptions.required;
if (attributeOptions.adminOnly !== undefined) body.adminOnly = attributeOptions.adminOnly;
if (attributeOptions.isPrivate !== undefined) body.isPrivate = attributeOptions.isPrivate;
if (attributeOptions.sortOrder !== undefined) body.sortOrder = attributeOptions.sortOrder;
if (attributeOptions.regex) body.regex = attributeOptions.regex;
if (attributeOptions.possibleValues) body.possibleValues = attributeOptions.possibleValues.split(',').map((v: string) => v.trim());
responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Attributes/${attributeId}`, body);
} else if (operation === 'delete') {
const attributeId = this.getNodeParameter('attributeId', i) as number;
responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Attributes/${attributeId}`);
}
}
// Process response
if (responseData) {
if (Array.isArray(responseData)) {
returnData.push(...responseData.map(item => ({ json: item })));
} else if (responseData.reservations) {
returnData.push(...responseData.reservations.map((item: any) => ({ json: item })));
} else if (responseData.resources) {
returnData.push(...responseData.resources.map((item: any) => ({ json: item })));
} else if (responseData.schedules) {
returnData.push(...responseData.schedules.map((item: any) => ({ json: item })));
} else if (responseData.users) {
returnData.push(...responseData.users.map((item: any) => ({ json: item })));
} else if (responseData.groups) {
returnData.push(...responseData.groups.map((item: any) => ({ json: item })));
} else if (responseData.accessories) {
returnData.push(...responseData.accessories.map((item: any) => ({ json: item })));
} else if (responseData.attributes) {
returnData.push(...responseData.attributes.map((item: any) => ({ json: item })));
} else {
returnData.push({ json: responseData });
}
}
} catch (error: any) {
if (this.continueOnFail()) {
returnData.push({ json: { error: error.message } });
continue;
}
throw error;
}
}
} finally {
await signOut(this, baseUrl, session);
}
return [returnData];
}
}