@joshuanode/n8n-nodes-cipp 0.0.22 → 0.0.25

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.
@@ -1,9 +1,11 @@
1
- import type { Icon, ICredentialType, INodeProperties } from 'n8n-workflow';
1
+ import type { ICredentialDataDecryptedObject, ICredentialType, IHttpRequestOptions, INodeProperties, Icon } from 'n8n-workflow';
2
2
  export declare class CippApi implements ICredentialType {
3
3
  name: string;
4
4
  displayName: string;
5
5
  icon: Icon;
6
6
  documentationUrl: string;
7
+ genericAuth: boolean;
7
8
  properties: INodeProperties[];
9
+ authenticate(credentials: ICredentialDataDecryptedObject, requestOptions: IHttpRequestOptions): Promise<IHttpRequestOptions>;
8
10
  }
9
11
  //# sourceMappingURL=CippApi.credentials.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CippApi.credentials.d.ts","sourceRoot":"","sources":["../../credentials/CippApi.credentials.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE3E,qBAAa,OAAQ,YAAW,eAAe;IAC9C,IAAI,SAAa;IACjB,WAAW,SAAkB;IAC7B,IAAI,EAAE,IAAI,CAAmB;IAC7B,gBAAgB,SAAsE;IAEtF,UAAU,EAAE,eAAe,EAAE,CAqC3B;CAIF"}
1
+ {"version":3,"file":"CippApi.credentials.d.ts","sourceRoot":"","sources":["../../credentials/CippApi.credentials.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,8BAA8B,EAC9B,eAAe,EAEf,mBAAmB,EACnB,eAAe,EACf,IAAI,EACJ,MAAM,cAAc,CAAC;AA6EtB,qBAAa,OAAQ,YAAW,eAAe;IAC9C,IAAI,SAAa;IACjB,WAAW,SAAkB;IAC7B,IAAI,EAAE,IAAI,CAAmB;IAC7B,gBAAgB,SAAsE;IACtF,WAAW,UAAQ;IAEnB,UAAU,EAAE,eAAe,EAAE,CAqC3B;IAEI,YAAY,CACjB,WAAW,EAAE,8BAA8B,EAC3C,cAAc,EAAE,mBAAmB,GACjC,OAAO,CAAC,mBAAmB,CAAC;CAW/B"}
@@ -1,11 +1,61 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CippApi = void 0;
4
+ const tokenCache = new Map();
5
+ function getCredentialString(credentials, name) {
6
+ const value = credentials[name];
7
+ if (typeof value !== 'string' || value.trim() === '') {
8
+ throw new Error(`Missing required CIPP credential field: ${name}`);
9
+ }
10
+ return value.trim();
11
+ }
12
+ function getCacheKey(clientId, tenantId) {
13
+ return `${clientId}:${tenantId}`;
14
+ }
15
+ async function getAccessToken(credentials) {
16
+ const tenantId = getCredentialString(credentials, 'tenantId');
17
+ const clientId = getCredentialString(credentials, 'clientId');
18
+ const clientSecret = getCredentialString(credentials, 'clientSecret');
19
+ const cacheKey = getCacheKey(clientId, tenantId);
20
+ const cached = tokenCache.get(cacheKey);
21
+ if (cached && cached.expiresAt > Date.now() + 300000) {
22
+ return cached.accessToken;
23
+ }
24
+ const tokenUrl = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`;
25
+ const body = new URLSearchParams({
26
+ grant_type: 'client_credentials',
27
+ client_id: clientId,
28
+ client_secret: clientSecret,
29
+ scope: `api://${clientId}/.default`,
30
+ });
31
+ const response = await fetch(tokenUrl, {
32
+ method: 'POST',
33
+ headers: {
34
+ 'Content-Type': 'application/x-www-form-urlencoded',
35
+ },
36
+ body,
37
+ });
38
+ const responseBody = (await response.json().catch(() => ({})));
39
+ if (!response.ok || typeof responseBody.access_token !== 'string') {
40
+ tokenCache.delete(cacheKey);
41
+ const message = responseBody.error_description ||
42
+ responseBody.error ||
43
+ `Azure AD token request failed with status ${response.status}`;
44
+ throw new Error(message);
45
+ }
46
+ const expiresIn = typeof responseBody.expires_in === 'number' ? responseBody.expires_in : 3600;
47
+ tokenCache.set(cacheKey, {
48
+ accessToken: responseBody.access_token,
49
+ expiresAt: Date.now() + expiresIn * 1000,
50
+ });
51
+ return responseBody.access_token;
52
+ }
4
53
  class CippApi {
5
54
  name = 'cippApi';
6
55
  displayName = 'CIPP.app API';
7
56
  icon = 'file:cipp.png';
8
57
  documentationUrl = 'https://docs.cipp.app/api-documentation/setup-and-authentication';
58
+ genericAuth = true;
9
59
  properties = [
10
60
  {
11
61
  displayName: 'CIPP Instance URL',
@@ -44,6 +94,15 @@ class CippApi {
44
94
  description: 'The Client Secret from your CIPP-SAM Azure AD App Registration',
45
95
  },
46
96
  ];
97
+ async authenticate(credentials, requestOptions) {
98
+ const accessToken = await getAccessToken(credentials);
99
+ requestOptions.headers = {
100
+ ...(requestOptions.headers ?? {}),
101
+ Authorization: `Bearer ${accessToken}`,
102
+ Accept: 'application/json',
103
+ };
104
+ return requestOptions;
105
+ }
47
106
  }
48
107
  exports.CippApi = CippApi;
49
108
  //# sourceMappingURL=CippApi.credentials.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CippApi.credentials.js","sourceRoot":"","sources":["../../credentials/CippApi.credentials.ts"],"names":[],"mappings":";;;AAEA,MAAa,OAAO;IACnB,IAAI,GAAG,SAAS,CAAC;IACjB,WAAW,GAAG,cAAc,CAAC;IAC7B,IAAI,GAAS,eAAe,CAAC;IAC7B,gBAAgB,GAAG,kEAAkE,CAAC;IAEtF,UAAU,GAAsB;QAC/B;YACC,WAAW,EAAE,mBAAmB;YAChC,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,6BAA6B;YAC1C,WAAW,EAAE,gDAAgD;SAC7D;QACD;YACC,WAAW,EAAE,oBAAoB;YACjC,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,sCAAsC;YACnD,WAAW,EAAE,qEAAqE;SAClF;QACD;YACC,WAAW,EAAE,yBAAyB;YACtC,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,sCAAsC;YACnD,WAAW,EAAE,0EAA0E;SACvF;QACD;YACC,WAAW,EAAE,eAAe;YAC5B,IAAI,EAAE,cAAc;YACpB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;YAC/B,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,gEAAgE;SAC7E;KACD,CAAC;CAIF;AA/CD,0BA+CC"}
1
+ {"version":3,"file":"CippApi.credentials.js","sourceRoot":"","sources":["../../credentials/CippApi.credentials.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Cipp.node.d.ts","sourceRoot":"","sources":["../../../nodes/Cipp/Cipp.node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,qBAAqB,EACrB,wBAAwB,EAExB,iBAAiB,EAEjB,qBAAqB,EACrB,yBAAyB,EACzB,kBAAkB,EAClB,qBAAqB,EACrB,SAAS,EACT,oBAAoB,EACpB,MAAM,cAAc,CAAC;AAWtB,qBAAa,IAAK,YAAW,SAAS;IACrC,WAAW,EAAE,oBAAoB,CAyK/B;IAEF,OAAO;;wCAGE,wBAAwB,cAClB,qBAAqB,GAC/B,OAAO,CAAC,yBAAyB,CAAC;;;+BAyD9B,qBAAqB,WAClB,MAAM,GACb,OAAO,CAAC,qBAAqB,CAAC;;MAqBjC;IAEI,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;CA6uHvE"}
1
+ {"version":3,"file":"Cipp.node.d.ts","sourceRoot":"","sources":["../../../nodes/Cipp/Cipp.node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,qBAAqB,EACrB,wBAAwB,EAExB,iBAAiB,EAEjB,qBAAqB,EACrB,yBAAyB,EACzB,kBAAkB,EAClB,qBAAqB,EACrB,SAAS,EACT,oBAAoB,EACpB,MAAM,cAAc,CAAC;AAWtB,qBAAa,IAAK,YAAW,SAAS;IACrC,WAAW,EAAE,oBAAoB,CAyK/B;IAEF,OAAO;;wCAGE,wBAAwB,cAClB,qBAAqB,GAC/B,OAAO,CAAC,yBAAyB,CAAC;;;+BAyD9B,qBAAqB,WAClB,MAAM,GACb,OAAO,CAAC,qBAAqB,CAAC;;MAqBjC;IAEI,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;CA6wHvE"}
@@ -537,15 +537,29 @@ class Cipp {
537
537
  const users = this.getNodeParameter('usersToOffboard', i);
538
538
  const scheduled = this.getNodeParameter('scheduledOffboard', i);
539
539
  const offboardOptions = this.getNodeParameter('offboardOptions', i, {});
540
+ const parsedUsers = parseJsonPayload(users, 'Users to Offboard', i);
541
+ const userValues = (Array.isArray(parsedUsers) ? parsedUsers : [parsedUsers])
542
+ .map((user) => {
543
+ if (typeof user === 'string')
544
+ return user;
545
+ return (user.value ??
546
+ user.userPrincipalName ??
547
+ user.UserPrincipalName ??
548
+ user.mail ??
549
+ user.id);
550
+ })
551
+ .filter((user) => Boolean(user));
552
+ if (userValues.length === 0) {
553
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Users to Offboard must contain at least one user identifier.', { itemIndex: i });
554
+ }
540
555
  const offboardBody = {
541
556
  tenantFilter,
542
- user: JSON.parse(users),
557
+ user: { value: userValues },
543
558
  };
544
- // Only include Scheduled when enabled — omitting it triggers immediate execution
545
559
  if (scheduled) {
546
- offboardBody.Scheduled = { enabled: true };
560
+ const scheduledDate = this.getNodeParameter('scheduledOffboardDate', i);
561
+ offboardBody.Scheduled = { enabled: true, date: scheduledDate };
547
562
  }
548
- // Spread offboard options at the top level (CIPP expects them here, not on the user object)
549
563
  for (const [key, value] of Object.entries(offboardOptions)) {
550
564
  if (value !== undefined && value !== '' && value !== false) {
551
565
  offboardBody[key] = value;
@@ -691,17 +705,16 @@ class Cipp {
691
705
  }
692
706
  else if (operation === 'bulkLicense') {
693
707
  const licenseJson = this.getNodeParameter('licenseJson', i);
694
- let parsedLicense;
695
- try {
696
- parsedLicense = JSON.parse(typeof licenseJson === 'string' ? licenseJson : '{}');
697
- }
698
- catch (e) {
699
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'License JSON must be valid JSON', { itemIndex: i });
700
- }
701
- responseData = await GenericFunctions_1.cippApiRequest.call(this, 'POST', '/api/ExecBulkLicense', {
702
- ...parsedLicense,
708
+ const parsedLicense = parseJsonPayload(licenseJson, 'License JSON', i);
709
+ const licenseRequests = (Array.isArray(parsedLicense)
710
+ ? parsedLicense
711
+ : Array.isArray(parsedLicense.requests)
712
+ ? parsedLicense.requests
713
+ : [parsedLicense]).map((request) => ({
703
714
  tenantFilter,
704
- }, {});
715
+ ...request,
716
+ }));
717
+ responseData = await GenericFunctions_1.cippApiRequest.call(this, 'POST', '/api/ExecBulkLicense', licenseRequests, {});
705
718
  }
706
719
  }
707
720
  // ==================== GROUP ====================
@@ -1188,7 +1201,7 @@ class Cipp {
1188
1201
  const autoReplyState = this.getNodeParameter('autoReplyState', i);
1189
1202
  const body = {
1190
1203
  tenantFilter,
1191
- user: userId,
1204
+ userId,
1192
1205
  AutoReplyState: autoReplyState,
1193
1206
  };
1194
1207
  if (autoReplyState === 'Enabled') {
@@ -1198,14 +1211,22 @@ class Cipp {
1198
1211
  }
1199
1212
  else if (operation === 'setForwarding') {
1200
1213
  const userId = this.getNodeParameter('userId', i);
1214
+ const forwardingType = this.getNodeParameter('forwardingType', i);
1201
1215
  const forwardTo = this.getNodeParameter('forwardTo', i);
1202
1216
  const keepCopy = this.getNodeParameter('keepCopy', i);
1203
- responseData = await GenericFunctions_1.cippApiRequest.call(this, 'POST', '/api/ExecEmailForward', {
1217
+ const body = {
1204
1218
  tenantFilter,
1205
- user: userId,
1206
- ForwardTo: forwardTo,
1207
- KeepCopy: keepCopy,
1208
- }, {});
1219
+ userID: userId,
1220
+ forwardOption: forwardTo ? forwardingType : 'disabled',
1221
+ KeepCopy: String(keepCopy),
1222
+ };
1223
+ if (forwardTo && forwardingType === 'internalAddress') {
1224
+ body.ForwardInternal = forwardTo;
1225
+ }
1226
+ else if (forwardTo) {
1227
+ body.ForwardExternal = forwardTo;
1228
+ }
1229
+ responseData = await GenericFunctions_1.cippApiRequest.call(this, 'POST', '/api/ExecEmailForward', body, {});
1209
1230
  // ---------- Edit Mailbox Permissions ----------
1210
1231
  }
1211
1232
  else if (operation === 'editMailboxPermissions') {