@vaiyen_og/n8n-nodes-ninjaone 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +142 -0
- package/dist/credentials/NinjaOneClientCredentialsApi.credentials.d.ts +10 -0
- package/dist/credentials/NinjaOneClientCredentialsApi.credentials.js +78 -0
- package/dist/credentials/NinjaOneClientCredentialsApi.credentials.js.map +1 -0
- package/dist/credentials/NinjaOneOAuth2Api.credentials.d.ts +10 -0
- package/dist/credentials/NinjaOneOAuth2Api.credentials.js +79 -0
- package/dist/credentials/NinjaOneOAuth2Api.credentials.js.map +1 -0
- package/dist/nodes/NinjaOne/GenericFunctions.d.ts +14 -0
- package/dist/nodes/NinjaOne/GenericFunctions.js +98 -0
- package/dist/nodes/NinjaOne/GenericFunctions.js.map +1 -0
- package/dist/nodes/NinjaOne/NinjaOne.node.d.ts +10 -0
- package/dist/nodes/NinjaOne/NinjaOne.node.js +713 -0
- package/dist/nodes/NinjaOne/NinjaOne.node.js.map +1 -0
- package/dist/nodes/NinjaOne/NinjaOneTrigger.node.d.ts +12 -0
- package/dist/nodes/NinjaOne/NinjaOneTrigger.node.js +108 -0
- package/dist/nodes/NinjaOne/NinjaOneTrigger.node.js.map +1 -0
- package/dist/nodes/NinjaOne/descriptions/DeviceDescription.d.ts +3 -0
- package/dist/nodes/NinjaOne/descriptions/DeviceDescription.js +151 -0
- package/dist/nodes/NinjaOne/descriptions/DeviceDescription.js.map +1 -0
- package/dist/nodes/NinjaOne/descriptions/OrganizationDescription.d.ts +3 -0
- package/dist/nodes/NinjaOne/descriptions/OrganizationDescription.js +106 -0
- package/dist/nodes/NinjaOne/descriptions/OrganizationDescription.js.map +1 -0
- package/dist/nodes/NinjaOne/descriptions/OtherDescriptions.d.ts +27 -0
- package/dist/nodes/NinjaOne/descriptions/OtherDescriptions.js +30 -0
- package/dist/nodes/NinjaOne/descriptions/OtherDescriptions.js.map +1 -0
- package/dist/nodes/NinjaOne/descriptions/TicketingDescription.d.ts +3 -0
- package/dist/nodes/NinjaOne/descriptions/TicketingDescription.js +322 -0
- package/dist/nodes/NinjaOne/descriptions/TicketingDescription.js.map +1 -0
- package/dist/nodes/NinjaOne/ninjaone.png +0 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# @vaiyen_og/n8n-nodes-ninjaone
|
|
2
|
+
|
|
3
|
+
Vollständige **n8n Community Node** für die [NinjaOne](https://www.ninjaone.com/) RMM API (v2).
|
|
4
|
+
Unterstützt alle regionalen Instanzen (EU, US, OC, CA) mit OAuth2 Authorization Code **und** Client Credentials Authentifizierung.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
1. Öffne deine n8n-Instanz
|
|
9
|
+
2. Gehe zu **Settings → Community Nodes**
|
|
10
|
+
3. Klicke **Install**
|
|
11
|
+
4. Gib `@vaiyen_og/n8n-nodes-ninjaone` ein
|
|
12
|
+
5. Bestätige die Installation
|
|
13
|
+
|
|
14
|
+
## Authentifizierung
|
|
15
|
+
|
|
16
|
+
### Option 1: OAuth2 Authorization Code (für Ticket-Erstellung mit User-Kontext)
|
|
17
|
+
|
|
18
|
+
1. In NinjaOne: **Administration → Apps → API → Client App IDs → Add**
|
|
19
|
+
2. Plattform: **Web**
|
|
20
|
+
3. Wähle **Authorization Code** und **Refresh Token** als Grant Types
|
|
21
|
+
4. Scopes: `monitoring`, `management`, `control`
|
|
22
|
+
5. Redirect URI: `https://<dein-n8n>/rest/oauth2-credential/callback`
|
|
23
|
+
6. In n8n: Neue Credential erstellen → **NinjaOne OAuth2 API**
|
|
24
|
+
7. Toggle auf **OAuth2 (Authorization Code)**
|
|
25
|
+
8. Trage **Client ID**, **Client Secret** ein und wähle die **Region**
|
|
26
|
+
9. Klicke **Connect** zum Autorisieren
|
|
27
|
+
|
|
28
|
+
### Option 2: Client Credentials / Machine-to-Machine (für Kontakte, Lesen, etc.)
|
|
29
|
+
|
|
30
|
+
1. In NinjaOne: **Administration → Apps → API → Client App IDs → Add**
|
|
31
|
+
2. Plattform: **Machine-to-Machine**
|
|
32
|
+
3. Scopes: `monitoring`, `management`, `control`
|
|
33
|
+
4. In n8n: Neue Credential erstellen → **NinjaOne OAuth2 API**
|
|
34
|
+
5. Toggle auf **Client Credentials**
|
|
35
|
+
6. Trage **Client ID**, **Client Secret** ein und wähle die **Region**
|
|
36
|
+
7. Klicke **Save**
|
|
37
|
+
|
|
38
|
+
### Wann welche Credential?
|
|
39
|
+
|
|
40
|
+
- **OAuth2 Authorization Code** → Tickets erstellen/bearbeiten (braucht User-Kontext)
|
|
41
|
+
- **Client Credentials** → Kontakte lesen/erstellen, Devices auflisten, alles was keinen User-Kontext braucht
|
|
42
|
+
|
|
43
|
+
Du kannst beide Credentials im selben Workflow verwenden – einfach pro Node die passende auswählen.
|
|
44
|
+
|
|
45
|
+
## Unterstützte Ressourcen & Operationen
|
|
46
|
+
|
|
47
|
+
### Organization
|
|
48
|
+
- Create, Get, Get Many, Update, Delete
|
|
49
|
+
|
|
50
|
+
### Device
|
|
51
|
+
- Get, Get Many (mit Device Filter Syntax)
|
|
52
|
+
- Get Activities, Custom Fields, Disks, Network Interfaces, OS Patches, Processors, Software, Volumes
|
|
53
|
+
- Approve/Reject, Reboot, Run Script, Maintenance Mode
|
|
54
|
+
- Update Custom Fields
|
|
55
|
+
|
|
56
|
+
### Ticketing
|
|
57
|
+
- Create Ticket, Get Ticket, Get Many (per Board ID), Update, Delete
|
|
58
|
+
- Create Contact, Get Contacts
|
|
59
|
+
- Add Comment, Get Log Entries
|
|
60
|
+
- Get Boards, Statuses, Ticket Forms
|
|
61
|
+
|
|
62
|
+
### User
|
|
63
|
+
- Create, Get, Get Many, Update, Delete
|
|
64
|
+
|
|
65
|
+
### Group
|
|
66
|
+
- Get, Get Many, Get Device IDs
|
|
67
|
+
|
|
68
|
+
### Query (Bulk-Abfragen)
|
|
69
|
+
- Alerts, Antivirus Status, Antivirus Threats, Custom Fields
|
|
70
|
+
- Device Health, Disks, Network Interfaces
|
|
71
|
+
- OS Patches, OS Patch Installs, Processors
|
|
72
|
+
- RAID Drives, Software, Software Patches, Windows Services
|
|
73
|
+
|
|
74
|
+
### Alert
|
|
75
|
+
- Get Many, Reset, Reset with Activity Data
|
|
76
|
+
|
|
77
|
+
### Location
|
|
78
|
+
- Create, Get Many, Update
|
|
79
|
+
|
|
80
|
+
### Backup
|
|
81
|
+
- Get Backup Jobs, Get Integrity Check Results
|
|
82
|
+
|
|
83
|
+
### Webhook
|
|
84
|
+
- Configure (Create/Update), Delete
|
|
85
|
+
|
|
86
|
+
### Custom Field
|
|
87
|
+
- Get/Update Device Custom Fields
|
|
88
|
+
- Get/Update Organization Custom Fields
|
|
89
|
+
|
|
90
|
+
### Knowledge Base Article
|
|
91
|
+
- Create, Get, Get Many, Update, Delete
|
|
92
|
+
|
|
93
|
+
### Organization Document
|
|
94
|
+
- Create, Get, Get Many, Update, Delete
|
|
95
|
+
|
|
96
|
+
### Document Template
|
|
97
|
+
- Get, Get Many
|
|
98
|
+
|
|
99
|
+
### Related Item
|
|
100
|
+
- Create, Get Many, Delete
|
|
101
|
+
|
|
102
|
+
## Trigger Node
|
|
103
|
+
|
|
104
|
+
Der **NinjaOne Trigger** Node empfängt Webhook-Events in Echtzeit:
|
|
105
|
+
|
|
106
|
+
- Alert Triggered/Reset
|
|
107
|
+
- Condition Triggered/Reset
|
|
108
|
+
- Device Added/Deleted/Online/Offline/Approval
|
|
109
|
+
- Patch Management
|
|
110
|
+
- Script Run
|
|
111
|
+
- Ticket Created/Updated/Deleted
|
|
112
|
+
|
|
113
|
+
## Device Filter Syntax
|
|
114
|
+
|
|
115
|
+
Viele Endpoints unterstützen die NinjaOne Device Filter Syntax (Parameter `df`), z.B.:
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
class in (WINDOWS_WORKSTATION, WINDOWS_SERVER)
|
|
119
|
+
org = 1
|
|
120
|
+
status = ONLINE
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Siehe [NinjaOne Device Filter Dokumentation](https://resources.ninjarmm.com/API/Ninja+RMM+Public+API+v2.0.5+Device+Filter+Syntax.pdf).
|
|
124
|
+
|
|
125
|
+
## API Regionen
|
|
126
|
+
|
|
127
|
+
| Region | Base URL |
|
|
128
|
+
|----------|-----------------------------|
|
|
129
|
+
| EU | `https://eu.ninjarmm.com` |
|
|
130
|
+
| US | `https://app.ninjarmm.com` |
|
|
131
|
+
| Oceania | `https://oc.ninjarmm.com` |
|
|
132
|
+
| Canada | `https://ca.ninjarmm.com` |
|
|
133
|
+
|
|
134
|
+
## Lizenz
|
|
135
|
+
|
|
136
|
+
MIT
|
|
137
|
+
|
|
138
|
+
## Links
|
|
139
|
+
|
|
140
|
+
- [NinjaOne API Docs (EU)](https://eu.ninjarmm.com/apidocs/?links.active=core)
|
|
141
|
+
- [NinjaOne OAuth Setup](https://www.ninjaone.com/docs/application-programming-interface-api/oauth-token-configuration/)
|
|
142
|
+
- [n8n Community Nodes Docs](https://docs.n8n.io/integrations/community-nodes/)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ICredentialDataDecryptedObject, ICredentialType, IHttpRequestOptions, INodeProperties } from 'n8n-workflow';
|
|
2
|
+
export declare class NinjaOneClientCredentialsApi implements ICredentialType {
|
|
3
|
+
name: string;
|
|
4
|
+
displayName: string;
|
|
5
|
+
documentationUrl: string;
|
|
6
|
+
properties: INodeProperties[];
|
|
7
|
+
authenticate(credentials: ICredentialDataDecryptedObject, requestOptions: IHttpRequestOptions): Promise<IHttpRequestOptions>;
|
|
8
|
+
private getBaseUrl;
|
|
9
|
+
private getAccessToken;
|
|
10
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NinjaOneClientCredentialsApi = void 0;
|
|
4
|
+
class NinjaOneClientCredentialsApi {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'ninjaOneClientCredentialsApi';
|
|
7
|
+
this.displayName = 'NinjaOne Client Credentials API';
|
|
8
|
+
this.documentationUrl = 'https://www.ninjaone.com/docs/application-programming-interface-api/oauth-token-configuration/';
|
|
9
|
+
this.properties = [
|
|
10
|
+
{
|
|
11
|
+
displayName: 'Region',
|
|
12
|
+
name: 'region',
|
|
13
|
+
type: 'options',
|
|
14
|
+
options: [
|
|
15
|
+
{ name: 'EU (eu.ninjarmm.com)', value: 'eu' },
|
|
16
|
+
{ name: 'US (app.ninjarmm.com)', value: 'us' },
|
|
17
|
+
{ name: 'Oceania (oc.ninjarmm.com)', value: 'oc' },
|
|
18
|
+
{ name: 'CA (ca.ninjarmm.com)', value: 'ca' },
|
|
19
|
+
],
|
|
20
|
+
default: 'eu',
|
|
21
|
+
description: 'The NinjaOne regional instance to connect to',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
displayName: 'Client ID',
|
|
25
|
+
name: 'clientId',
|
|
26
|
+
type: 'string',
|
|
27
|
+
default: '',
|
|
28
|
+
required: true,
|
|
29
|
+
description: 'OAuth2 Client ID from NinjaOne (Administration → Apps → API)',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
displayName: 'Client Secret',
|
|
33
|
+
name: 'clientSecret',
|
|
34
|
+
type: 'string',
|
|
35
|
+
typeOptions: { password: true },
|
|
36
|
+
default: '',
|
|
37
|
+
required: true,
|
|
38
|
+
description: 'OAuth2 Client Secret from NinjaOne',
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
async authenticate(credentials, requestOptions) {
|
|
43
|
+
const region = credentials.region;
|
|
44
|
+
const baseUrl = this.getBaseUrl(region);
|
|
45
|
+
const tokenResponse = await this.getAccessToken(baseUrl, credentials.clientId, credentials.clientSecret);
|
|
46
|
+
requestOptions.headers = {
|
|
47
|
+
...requestOptions.headers,
|
|
48
|
+
Authorization: `Bearer ${tokenResponse}`,
|
|
49
|
+
};
|
|
50
|
+
return requestOptions;
|
|
51
|
+
}
|
|
52
|
+
getBaseUrl(region) {
|
|
53
|
+
switch (region) {
|
|
54
|
+
case 'eu': return 'https://eu.ninjarmm.com';
|
|
55
|
+
case 'oc': return 'https://oc.ninjarmm.com';
|
|
56
|
+
case 'ca': return 'https://ca.ninjarmm.com';
|
|
57
|
+
default: return 'https://app.ninjarmm.com';
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async getAccessToken(baseUrl, clientId, clientSecret) {
|
|
61
|
+
const url = `${baseUrl}/ws/oauth/token`;
|
|
62
|
+
const params = new URLSearchParams({
|
|
63
|
+
grant_type: 'client_credentials',
|
|
64
|
+
client_id: clientId,
|
|
65
|
+
client_secret: clientSecret,
|
|
66
|
+
scope: 'monitoring management control',
|
|
67
|
+
});
|
|
68
|
+
const response = await fetch(url, {
|
|
69
|
+
method: 'POST',
|
|
70
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
71
|
+
body: params.toString(),
|
|
72
|
+
});
|
|
73
|
+
const data = await response.json();
|
|
74
|
+
return data.access_token;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.NinjaOneClientCredentialsApi = NinjaOneClientCredentialsApi;
|
|
78
|
+
//# sourceMappingURL=NinjaOneClientCredentialsApi.credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NinjaOneClientCredentialsApi.credentials.js","sourceRoot":"","sources":["../../credentials/NinjaOneClientCredentialsApi.credentials.ts"],"names":[],"mappings":";;;AAOA,MAAa,4BAA4B;IAAzC;QACC,SAAI,GAAG,8BAA8B,CAAC;QACtC,gBAAW,GAAG,iCAAiC,CAAC;QAChD,qBAAgB,GAAG,gGAAgG,CAAC;QAEpH,eAAU,GAAsB;YAC/B;gBACC,WAAW,EAAE,QAAQ;gBACrB,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE;oBACR,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,IAAI,EAAE;oBAC7C,EAAE,IAAI,EAAE,uBAAuB,EAAE,KAAK,EAAE,IAAI,EAAE;oBAC9C,EAAE,IAAI,EAAE,2BAA2B,EAAE,KAAK,EAAE,IAAI,EAAE;oBAClD,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,IAAI,EAAE;iBAC7C;gBACD,OAAO,EAAE,IAAI;gBACb,WAAW,EAAE,8CAA8C;aAC3D;YACD;gBACC,WAAW,EAAE,WAAW;gBACxB,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,8DAA8D;aAC3E;YACD;gBACC,WAAW,EAAE,eAAe;gBAC5B,IAAI,EAAE,cAAc;gBACpB,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC/B,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,oCAAoC;aACjD;SACD,CAAC;IAsDH,CAAC;IApDA,KAAK,CAAC,YAAY,CACjB,WAA2C,EAC3C,cAAmC;QAEnC,MAAM,MAAM,GAAG,WAAW,CAAC,MAAgB,CAAC;QAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAExC,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,cAAc,CAC9C,OAAO,EACP,WAAW,CAAC,QAAkB,EAC9B,WAAW,CAAC,YAAsB,CAClC,CAAC;QAEF,cAAc,CAAC,OAAO,GAAG;YACxB,GAAG,cAAc,CAAC,OAAO;YACzB,aAAa,EAAE,UAAU,aAAa,EAAE;SACxC,CAAC;QAEF,OAAO,cAAc,CAAC;IACvB,CAAC;IAEO,UAAU,CAAC,MAAc;QAChC,QAAQ,MAAM,EAAE,CAAC;YAChB,KAAK,IAAI,CAAC,CAAC,OAAO,yBAAyB,CAAC;YAC5C,KAAK,IAAI,CAAC,CAAC,OAAO,yBAAyB,CAAC;YAC5C,KAAK,IAAI,CAAC,CAAC,OAAO,yBAAyB,CAAC;YAC5C,OAAO,CAAC,CAAC,OAAO,0BAA0B,CAAC;QAC5C,CAAC;IACF,CAAC;IAEO,KAAK,CAAC,cAAc,CAC3B,OAAe,EACf,QAAgB,EAChB,YAAoB;QAEpB,MAAM,GAAG,GAAG,GAAG,OAAO,iBAAiB,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;YAClC,UAAU,EAAE,oBAAoB;YAChC,SAAS,EAAE,QAAQ;YACnB,aAAa,EAAE,YAAY;YAC3B,KAAK,EAAE,+BAA+B;SACtC,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YACjC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,mCAAmC,EAAE;YAChE,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE;SACvB,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAA8B,CAAC;QAC/D,OAAO,IAAI,CAAC,YAAY,CAAC;IAC1B,CAAC;CACD;AA1FD,oEA0FC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
|
|
2
|
+
export declare class NinjaOneOAuth2Api implements ICredentialType {
|
|
3
|
+
name: string;
|
|
4
|
+
displayName: string;
|
|
5
|
+
documentationUrl: string;
|
|
6
|
+
extends: string[];
|
|
7
|
+
properties: INodeProperties[];
|
|
8
|
+
authenticate: IAuthenticateGeneric;
|
|
9
|
+
test: ICredentialTestRequest;
|
|
10
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NinjaOneOAuth2Api = void 0;
|
|
4
|
+
class NinjaOneOAuth2Api {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'ninjaOneOAuth2Api';
|
|
7
|
+
this.displayName = 'NinjaOne OAuth2 API';
|
|
8
|
+
this.documentationUrl = 'https://www.ninjaone.com/docs/application-programming-interface-api/oauth-token-configuration/';
|
|
9
|
+
this.extends = ['oAuth2Api'];
|
|
10
|
+
this.properties = [
|
|
11
|
+
{
|
|
12
|
+
displayName: 'Region',
|
|
13
|
+
name: 'region',
|
|
14
|
+
type: 'options',
|
|
15
|
+
options: [
|
|
16
|
+
{ name: 'EU (eu.ninjarmm.com)', value: 'eu' },
|
|
17
|
+
{ name: 'US (app.ninjarmm.com)', value: 'us' },
|
|
18
|
+
{ name: 'Oceania (oc.ninjarmm.com)', value: 'oc' },
|
|
19
|
+
{ name: 'CA (ca.ninjarmm.com)', value: 'ca' },
|
|
20
|
+
],
|
|
21
|
+
default: 'eu',
|
|
22
|
+
description: 'The NinjaOne regional instance to connect to',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
displayName: 'Grant Type',
|
|
26
|
+
name: 'grantType',
|
|
27
|
+
type: 'hidden',
|
|
28
|
+
default: 'authorizationCode',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
displayName: 'Authorization URL',
|
|
32
|
+
name: 'authUrl',
|
|
33
|
+
type: 'hidden',
|
|
34
|
+
default: '={{$self["region"] === "eu" ? "https://eu.ninjarmm.com" : $self["region"] === "oc" ? "https://oc.ninjarmm.com" : $self["region"] === "ca" ? "https://ca.ninjarmm.com" : "https://app.ninjarmm.com"}}/ws/oauth/authorize',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
displayName: 'Access Token URL',
|
|
38
|
+
name: 'accessTokenUrl',
|
|
39
|
+
type: 'hidden',
|
|
40
|
+
default: '={{$self["region"] === "eu" ? "https://eu.ninjarmm.com" : $self["region"] === "oc" ? "https://oc.ninjarmm.com" : $self["region"] === "ca" ? "https://ca.ninjarmm.com" : "https://app.ninjarmm.com"}}/ws/oauth/token',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
displayName: 'Scope',
|
|
44
|
+
name: 'scope',
|
|
45
|
+
type: 'hidden',
|
|
46
|
+
default: 'monitoring management control offline_access',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
displayName: 'Auth URI Query Parameters',
|
|
50
|
+
name: 'authQueryParameters',
|
|
51
|
+
type: 'hidden',
|
|
52
|
+
default: 'response_type=code',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
displayName: 'Authentication',
|
|
56
|
+
name: 'authentication',
|
|
57
|
+
type: 'hidden',
|
|
58
|
+
default: 'header',
|
|
59
|
+
},
|
|
60
|
+
];
|
|
61
|
+
this.authenticate = {
|
|
62
|
+
type: 'generic',
|
|
63
|
+
properties: {
|
|
64
|
+
headers: {
|
|
65
|
+
Authorization: '=Bearer {{$credentials.oauthTokenData.access_token}}',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
this.test = {
|
|
70
|
+
request: {
|
|
71
|
+
baseURL: '={{$credentials.region === "eu" ? "https://eu.ninjarmm.com" : $credentials.region === "oc" ? "https://oc.ninjarmm.com" : $credentials.region === "ca" ? "https://ca.ninjarmm.com" : "https://app.ninjarmm.com"}}',
|
|
72
|
+
url: '/api/v2/organizations',
|
|
73
|
+
method: 'GET',
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.NinjaOneOAuth2Api = NinjaOneOAuth2Api;
|
|
79
|
+
//# sourceMappingURL=NinjaOneOAuth2Api.credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NinjaOneOAuth2Api.credentials.js","sourceRoot":"","sources":["../../credentials/NinjaOneOAuth2Api.credentials.ts"],"names":[],"mappings":";;;AAOA,MAAa,iBAAiB;IAA9B;QACC,SAAI,GAAG,mBAAmB,CAAC;QAC3B,gBAAW,GAAG,qBAAqB,CAAC;QACpC,qBAAgB,GAAG,gGAAgG,CAAC;QACpH,YAAO,GAAG,CAAC,WAAW,CAAC,CAAC;QAExB,eAAU,GAAsB;YAC/B;gBACC,WAAW,EAAE,QAAQ;gBACrB,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE;oBACR,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,IAAI,EAAE;oBAC7C,EAAE,IAAI,EAAE,uBAAuB,EAAE,KAAK,EAAE,IAAI,EAAE;oBAC9C,EAAE,IAAI,EAAE,2BAA2B,EAAE,KAAK,EAAE,IAAI,EAAE;oBAClD,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,IAAI,EAAE;iBAC7C;gBACD,OAAO,EAAE,IAAI;gBACb,WAAW,EAAE,8CAA8C;aAC3D;YACD;gBACC,WAAW,EAAE,YAAY;gBACzB,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,mBAAmB;aAC5B;YACD;gBACC,WAAW,EAAE,mBAAmB;gBAChC,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,QAAQ;gBACd,OAAO,EACN,yNAAyN;aAC1N;YACD;gBACC,WAAW,EAAE,kBAAkB;gBAC/B,IAAI,EAAE,gBAAgB;gBACtB,IAAI,EAAE,QAAQ;gBACd,OAAO,EACN,qNAAqN;aACtN;YACD;gBACC,WAAW,EAAE,OAAO;gBACpB,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,8CAA8C;aACvD;YACD;gBACC,WAAW,EAAE,2BAA2B;gBACxC,IAAI,EAAE,qBAAqB;gBAC3B,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,oBAAoB;aAC7B;YACD;gBACC,WAAW,EAAE,gBAAgB;gBAC7B,IAAI,EAAE,gBAAgB;gBACtB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,QAAQ;aACjB;SACD,CAAC;QAEF,iBAAY,GAAyB;YACpC,IAAI,EAAE,SAAS;YACf,UAAU,EAAE;gBACX,OAAO,EAAE;oBACR,aAAa,EAAE,sDAAsD;iBACrE;aACD;SACD,CAAC;QAEF,SAAI,GAA2B;YAC9B,OAAO,EAAE;gBACR,OAAO,EACN,kNAAkN;gBACnN,GAAG,EAAE,uBAAuB;gBAC5B,MAAM,EAAE,KAAK;aACb;SACD,CAAC;IACH,CAAC;CAAA;AA7ED,8CA6EC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { IExecuteFunctions, IHookFunctions, ILoadOptionsFunctions, IHttpRequestMethods, INodeExecutionData } from 'n8n-workflow';
|
|
2
|
+
/** Return the base URL for the selected NinjaOne region */
|
|
3
|
+
export declare function getBaseUrl(credentials: {
|
|
4
|
+
region?: string;
|
|
5
|
+
}): string;
|
|
6
|
+
/** Perform an authenticated request against the NinjaOne API */
|
|
7
|
+
export declare function ninjaOneApiRequest(this: IExecuteFunctions | ILoadOptionsFunctions | IHookFunctions, method: IHttpRequestMethods, endpoint: string, body?: object, qs?: Record<string, string | number | boolean | undefined>, uri?: string): Promise<any>;
|
|
8
|
+
/**
|
|
9
|
+
* Paginate through all results using cursor-based pagination (NinjaOne style).
|
|
10
|
+
* NinjaOne uses `pageSize` + `after` (last ID) for many list endpoints.
|
|
11
|
+
*/
|
|
12
|
+
export declare function ninjaOneApiRequestAllItems(this: IExecuteFunctions | ILoadOptionsFunctions, method: IHttpRequestMethods, endpoint: string, body?: object, qs?: Record<string, string | number | boolean | undefined>, idField?: string): Promise<any[]>;
|
|
13
|
+
/** Convert n8n items to proper output format */
|
|
14
|
+
export declare function toItems(data: any[]): INodeExecutionData[];
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toItems = exports.ninjaOneApiRequestAllItems = exports.ninjaOneApiRequest = exports.getBaseUrl = void 0;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
/** Return the base URL for the selected NinjaOne region */
|
|
6
|
+
function getBaseUrl(credentials) {
|
|
7
|
+
switch (credentials.region) {
|
|
8
|
+
case 'eu': return 'https://eu.ninjarmm.com';
|
|
9
|
+
case 'oc': return 'https://oc.ninjarmm.com';
|
|
10
|
+
case 'ca': return 'https://ca.ninjarmm.com';
|
|
11
|
+
default: return 'https://app.ninjarmm.com';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.getBaseUrl = getBaseUrl;
|
|
15
|
+
/** Perform an authenticated request against the NinjaOne API */
|
|
16
|
+
async function ninjaOneApiRequest(method, endpoint, body = {}, qs = {}, uri) {
|
|
17
|
+
const authType = this.getNodeParameter('authentication', 0, 'oAuth2');
|
|
18
|
+
const credentialName = authType === 'clientCredentials'
|
|
19
|
+
? 'ninjaOneClientCredentialsApi'
|
|
20
|
+
: 'ninjaOneOAuth2Api';
|
|
21
|
+
const credentials = await this.getCredentials(credentialName);
|
|
22
|
+
const baseUrl = uri ?? `${getBaseUrl(credentials)}${endpoint}`;
|
|
23
|
+
// Strip undefined qs values
|
|
24
|
+
const cleanQs = {};
|
|
25
|
+
for (const [k, v] of Object.entries(qs)) {
|
|
26
|
+
if (v !== undefined && v !== '')
|
|
27
|
+
cleanQs[k] = v;
|
|
28
|
+
}
|
|
29
|
+
const options = {
|
|
30
|
+
method,
|
|
31
|
+
url: baseUrl,
|
|
32
|
+
qs: cleanQs,
|
|
33
|
+
body,
|
|
34
|
+
json: true,
|
|
35
|
+
headers: {
|
|
36
|
+
Accept: 'application/json',
|
|
37
|
+
'Content-Type': 'application/json',
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
if (method === 'GET' || method === 'DELETE') {
|
|
41
|
+
delete options.body;
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
return await this.helpers.requestWithAuthentication.call(this, credentialName, options);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.ninjaOneApiRequest = ninjaOneApiRequest;
|
|
51
|
+
/**
|
|
52
|
+
* Paginate through all results using cursor-based pagination (NinjaOne style).
|
|
53
|
+
* NinjaOne uses `pageSize` + `after` (last ID) for many list endpoints.
|
|
54
|
+
*/
|
|
55
|
+
async function ninjaOneApiRequestAllItems(method, endpoint, body = {}, qs = {}, idField = 'id') {
|
|
56
|
+
const returnData = [];
|
|
57
|
+
let lastId;
|
|
58
|
+
qs.pageSize = qs.pageSize ?? 1000;
|
|
59
|
+
do {
|
|
60
|
+
if (lastId !== undefined) {
|
|
61
|
+
qs.after = lastId;
|
|
62
|
+
}
|
|
63
|
+
const responseData = await ninjaOneApiRequest.call(this, method, endpoint, body, qs);
|
|
64
|
+
if (Array.isArray(responseData)) {
|
|
65
|
+
returnData.push(...responseData);
|
|
66
|
+
if (responseData.length < qs.pageSize)
|
|
67
|
+
break;
|
|
68
|
+
const last = responseData[responseData.length - 1];
|
|
69
|
+
lastId = last?.[idField];
|
|
70
|
+
if (!lastId)
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
// Some endpoints return { results: [...] } or direct objects
|
|
75
|
+
if (responseData.results && Array.isArray(responseData.results)) {
|
|
76
|
+
returnData.push(...responseData.results);
|
|
77
|
+
if (responseData.results.length < qs.pageSize)
|
|
78
|
+
break;
|
|
79
|
+
const last = responseData.results[responseData.results.length - 1];
|
|
80
|
+
lastId = last?.[idField];
|
|
81
|
+
if (!lastId)
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
returnData.push(responseData);
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
} while (true);
|
|
90
|
+
return returnData;
|
|
91
|
+
}
|
|
92
|
+
exports.ninjaOneApiRequestAllItems = ninjaOneApiRequestAllItems;
|
|
93
|
+
/** Convert n8n items to proper output format */
|
|
94
|
+
function toItems(data) {
|
|
95
|
+
return data.map((item) => ({ json: item }));
|
|
96
|
+
}
|
|
97
|
+
exports.toItems = toItems;
|
|
98
|
+
//# sourceMappingURL=GenericFunctions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GenericFunctions.js","sourceRoot":"","sources":["../../../nodes/NinjaOne/GenericFunctions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription, ILoadOptionsFunctions, INodePropertyOptions } from 'n8n-workflow';
|
|
2
|
+
export declare class NinjaOne implements INodeType {
|
|
3
|
+
description: INodeTypeDescription;
|
|
4
|
+
methods: {
|
|
5
|
+
loadOptions: {
|
|
6
|
+
getOrganizations(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
10
|
+
}
|