@joshuanode/n8n-nodes-cipp 0.0.21 → 0.0.23

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.
Files changed (28) hide show
  1. package/dist/nodes/Cipp/Cipp.node.d.ts.map +1 -1
  2. package/dist/nodes/Cipp/Cipp.node.js +233 -20
  3. package/dist/nodes/Cipp/Cipp.node.js.map +1 -1
  4. package/dist/nodes/Cipp/GenericFunctions.d.ts +1 -1
  5. package/dist/nodes/Cipp/GenericFunctions.d.ts.map +1 -1
  6. package/dist/nodes/Cipp/GenericFunctions.js.map +1 -1
  7. package/dist/nodes/Cipp/descriptions/ApplicationDescription.d.ts.map +1 -1
  8. package/dist/nodes/Cipp/descriptions/ApplicationDescription.js +86 -2
  9. package/dist/nodes/Cipp/descriptions/ApplicationDescription.js.map +1 -1
  10. package/dist/nodes/Cipp/descriptions/CippDescription.d.ts.map +1 -1
  11. package/dist/nodes/Cipp/descriptions/CippDescription.js +164 -4
  12. package/dist/nodes/Cipp/descriptions/CippDescription.js.map +1 -1
  13. package/dist/nodes/Cipp/descriptions/ConditionalAccessDescription.d.ts.map +1 -1
  14. package/dist/nodes/Cipp/descriptions/ConditionalAccessDescription.js +7 -0
  15. package/dist/nodes/Cipp/descriptions/ConditionalAccessDescription.js.map +1 -1
  16. package/dist/nodes/Cipp/descriptions/EmailSecurityDescription.d.ts.map +1 -1
  17. package/dist/nodes/Cipp/descriptions/EmailSecurityDescription.js +7 -0
  18. package/dist/nodes/Cipp/descriptions/EmailSecurityDescription.js.map +1 -1
  19. package/dist/nodes/Cipp/descriptions/IdentityDescription.d.ts.map +1 -1
  20. package/dist/nodes/Cipp/descriptions/IdentityDescription.js +140 -2
  21. package/dist/nodes/Cipp/descriptions/IdentityDescription.js.map +1 -1
  22. package/dist/nodes/Cipp/descriptions/MailboxDescription.d.ts.map +1 -1
  23. package/dist/nodes/Cipp/descriptions/MailboxDescription.js +124 -1
  24. package/dist/nodes/Cipp/descriptions/MailboxDescription.js.map +1 -1
  25. package/dist/nodes/Cipp/descriptions/UserDescription.d.ts.map +1 -1
  26. package/dist/nodes/Cipp/descriptions/UserDescription.js +17 -2
  27. package/dist/nodes/Cipp/descriptions/UserDescription.js.map +1 -1
  28. package/package.json +1 -1
@@ -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,EACjB,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;CAk+GvE"}
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"}
@@ -289,6 +289,26 @@ class Cipp {
289
289
  };
290
290
  const hasPayloadContent = (payload) => Array.isArray(payload) ? payload.length > 0 : Object.keys(payload).length > 0;
291
291
  const isTeamsScheduleEndpoint = (endpoint) => /^teams\/[^/]+\/schedule(?:\/.*)?$/i.test(endpoint);
292
+ const normalizeCippEndpoint = (endpoint) => {
293
+ const trimmed = endpoint.trim();
294
+ if (!trimmed) {
295
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Endpoint is required.');
296
+ }
297
+ const withoutOrigin = trimmed.replace(/^https?:\/\/[^/]+/i, '');
298
+ const withLeadingSlash = withoutOrigin.startsWith('/') ? withoutOrigin : `/${withoutOrigin}`;
299
+ return withLeadingSlash.toLowerCase().startsWith('/api/')
300
+ ? withLeadingSlash
301
+ : `/api${withLeadingSlash}`;
302
+ };
303
+ const splitCsv = (value) => {
304
+ if (typeof value !== 'string' || value.trim() === '') {
305
+ return undefined;
306
+ }
307
+ return value
308
+ .split(',')
309
+ .map((entry) => entry.trim())
310
+ .filter(Boolean);
311
+ };
292
312
  for (let i = 0; i < items.length; i++) {
293
313
  try {
294
314
  let responseData = {};
@@ -517,15 +537,29 @@ class Cipp {
517
537
  const users = this.getNodeParameter('usersToOffboard', i);
518
538
  const scheduled = this.getNodeParameter('scheduledOffboard', i);
519
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
+ }
520
555
  const offboardBody = {
521
556
  tenantFilter,
522
- user: JSON.parse(users),
557
+ user: { value: userValues },
523
558
  };
524
- // Only include Scheduled when enabled — omitting it triggers immediate execution
525
559
  if (scheduled) {
526
- offboardBody.Scheduled = { enabled: true };
560
+ const scheduledDate = this.getNodeParameter('scheduledOffboardDate', i);
561
+ offboardBody.Scheduled = { enabled: true, date: scheduledDate };
527
562
  }
528
- // Spread offboard options at the top level (CIPP expects them here, not on the user object)
529
563
  for (const [key, value] of Object.entries(offboardOptions)) {
530
564
  if (value !== undefined && value !== '' && value !== false) {
531
565
  offboardBody[key] = value;
@@ -671,17 +705,16 @@ class Cipp {
671
705
  }
672
706
  else if (operation === 'bulkLicense') {
673
707
  const licenseJson = this.getNodeParameter('licenseJson', i);
674
- let parsedLicense;
675
- try {
676
- parsedLicense = JSON.parse(typeof licenseJson === 'string' ? licenseJson : '{}');
677
- }
678
- catch (e) {
679
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'License JSON must be valid JSON', { itemIndex: i });
680
- }
681
- responseData = await GenericFunctions_1.cippApiRequest.call(this, 'POST', '/api/ExecBulkLicense', {
682
- ...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) => ({
683
714
  tenantFilter,
684
- }, {});
715
+ ...request,
716
+ }));
717
+ responseData = await GenericFunctions_1.cippApiRequest.call(this, 'POST', '/api/ExecBulkLicense', licenseRequests, {});
685
718
  }
686
719
  }
687
720
  // ==================== GROUP ====================
@@ -783,6 +816,13 @@ class Cipp {
783
816
  responseData = responseData.slice(0, this.getNodeParameter('limit', i));
784
817
  }
785
818
  }
819
+ else if (operation === 'listPolicyChanges') {
820
+ const returnAll = this.getNodeParameter('returnAll', i);
821
+ responseData = await GenericFunctions_1.cippApiRequest.call(this, 'GET', '/api/ListConditionalAccessPolicyChanges', {}, { tenantFilter });
822
+ if (Array.isArray(responseData) && !returnAll) {
823
+ responseData = responseData.slice(0, this.getNodeParameter('limit', i));
824
+ }
825
+ }
786
826
  else if (operation === 'listTemplates') {
787
827
  const returnAll = this.getNodeParameter('returnAll', i);
788
828
  responseData = await GenericFunctions_1.cippApiRequest.call(this, 'GET', '/api/ListCAtemplates', {}, {});
@@ -1036,6 +1076,38 @@ class Cipp {
1036
1076
  if (Array.isArray(responseData) && !returnAll) {
1037
1077
  responseData = responseData.slice(0, this.getNodeParameter('limit', i));
1038
1078
  }
1079
+ }
1080
+ else if (operation === 'listMessageTrace') {
1081
+ const returnAll = this.getNodeParameter('returnAll', i);
1082
+ const filters = this.getNodeParameter('messageTraceFilters', i, {});
1083
+ const body = { tenantFilter };
1084
+ for (const key of [
1085
+ 'dateFilter',
1086
+ 'days',
1087
+ 'endDate',
1088
+ 'fromIP',
1089
+ 'MessageId',
1090
+ 'startDate',
1091
+ 'toIP',
1092
+ 'traceDetail',
1093
+ ]) {
1094
+ if (filters[key] !== undefined && filters[key] !== '') {
1095
+ body[key] = filters[key];
1096
+ }
1097
+ }
1098
+ const recipients = splitCsv(filters.recipient);
1099
+ const senders = splitCsv(filters.sender);
1100
+ const statuses = splitCsv(filters.status);
1101
+ if (recipients)
1102
+ body.recipient = recipients;
1103
+ if (senders)
1104
+ body.sender = senders;
1105
+ if (statuses)
1106
+ body.status = statuses;
1107
+ responseData = await GenericFunctions_1.cippApiRequest.call(this, 'POST', '/api/ListMessageTrace', body, {});
1108
+ if (Array.isArray(responseData) && !returnAll) {
1109
+ responseData = responseData.slice(0, this.getNodeParameter('limit', i));
1110
+ }
1039
1111
  // ---------- List operations (userId required) ----------
1040
1112
  }
1041
1113
  else if (operation === 'listMailboxDetails') {
@@ -1129,7 +1201,7 @@ class Cipp {
1129
1201
  const autoReplyState = this.getNodeParameter('autoReplyState', i);
1130
1202
  const body = {
1131
1203
  tenantFilter,
1132
- user: userId,
1204
+ userId,
1133
1205
  AutoReplyState: autoReplyState,
1134
1206
  };
1135
1207
  if (autoReplyState === 'Enabled') {
@@ -1139,14 +1211,22 @@ class Cipp {
1139
1211
  }
1140
1212
  else if (operation === 'setForwarding') {
1141
1213
  const userId = this.getNodeParameter('userId', i);
1214
+ const forwardingType = this.getNodeParameter('forwardingType', i);
1142
1215
  const forwardTo = this.getNodeParameter('forwardTo', i);
1143
1216
  const keepCopy = this.getNodeParameter('keepCopy', i);
1144
- responseData = await GenericFunctions_1.cippApiRequest.call(this, 'POST', '/api/ExecEmailForward', {
1217
+ const body = {
1145
1218
  tenantFilter,
1146
- user: userId,
1147
- ForwardTo: forwardTo,
1148
- KeepCopy: keepCopy,
1149
- }, {});
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, {});
1150
1230
  // ---------- Edit Mailbox Permissions ----------
1151
1231
  }
1152
1232
  else if (operation === 'editMailboxPermissions') {
@@ -1579,6 +1659,40 @@ class Cipp {
1579
1659
  responseData = responseData.slice(0, limit);
1580
1660
  }
1581
1661
  }
1662
+ else if (operation === 'listDetectedApps') {
1663
+ const returnAll = this.getNodeParameter('returnAll', i);
1664
+ const deviceId = this.getNodeParameter('detectedAppDeviceId', i, '');
1665
+ const includeDevices = this.getNodeParameter('detectedAppsIncludeDevices', i);
1666
+ const qs = { tenantFilter };
1667
+ if (deviceId)
1668
+ qs.DeviceID = deviceId;
1669
+ if (includeDevices)
1670
+ qs.includeDevices = 'true';
1671
+ responseData = await GenericFunctions_1.cippApiRequest.call(this, 'GET', '/api/ListDetectedApps', {}, qs);
1672
+ if (Array.isArray(responseData) && !returnAll) {
1673
+ const limit = this.getNodeParameter('limit', i);
1674
+ responseData = responseData.slice(0, limit);
1675
+ }
1676
+ }
1677
+ else if (operation === 'listDetectedAppDevices') {
1678
+ const returnAll = this.getNodeParameter('returnAll', i);
1679
+ const detectedAppId = this.getNodeParameter('detectedAppId', i);
1680
+ responseData = await GenericFunctions_1.cippApiRequest.call(this, 'GET', '/api/ListDetectedAppDevices', {}, { tenantFilter, id: detectedAppId });
1681
+ if (Array.isArray(responseData) && !returnAll) {
1682
+ const limit = this.getNodeParameter('limit', i);
1683
+ responseData = responseData.slice(0, limit);
1684
+ }
1685
+ }
1686
+ else if (operation === 'listAppRepository') {
1687
+ const search = this.getNodeParameter('appRepositorySearch', i, '');
1688
+ const repository = this.getNodeParameter('appRepositoryName', i, '');
1689
+ const body = { tenantFilter };
1690
+ if (search)
1691
+ body.Search = search;
1692
+ if (repository)
1693
+ body.Repository = repository;
1694
+ responseData = await GenericFunctions_1.cippApiRequest.call(this, 'POST', '/api/ListAppsRepository', body, {});
1695
+ }
1582
1696
  else if (operation === 'assign') {
1583
1697
  const appId = this.getNodeParameter('appId', i);
1584
1698
  const assignTo = this.getNodeParameter('assignTo', i);
@@ -2023,6 +2137,42 @@ class Cipp {
2023
2137
  const tenantFilter = getTenantFilter();
2024
2138
  responseData = await GenericFunctions_1.cippApiRequest.call(this, 'GET', '/api/ExecBreachSearch', {}, { tenantFilter });
2025
2139
  }
2140
+ else if (operation === 'getVersion') {
2141
+ const localVersion = this.getNodeParameter('localVersion', i, '');
2142
+ const qs = {};
2143
+ if (localVersion)
2144
+ qs.LocalVersion = localVersion;
2145
+ responseData = await GenericFunctions_1.cippApiRequest.call(this, 'GET', '/api/GetVersion', {}, qs);
2146
+ }
2147
+ else if (operation === 'cippApiRequest') {
2148
+ const method = this.getNodeParameter('cippApiMethod', i);
2149
+ const endpoint = normalizeCippEndpoint(this.getNodeParameter('cippApiEndpoint', i));
2150
+ const includeTenant = this.getNodeParameter('cippApiIncludeTenant', i);
2151
+ const query = parseJsonObjectPayload(this.getNodeParameter('cippApiQueryJson', i, '{}'), 'Query Parameters', i);
2152
+ const body = method === 'GET'
2153
+ ? {}
2154
+ : parseJsonObjectPayload(this.getNodeParameter('cippApiBodyJson', i, '{}'), 'Body', i);
2155
+ if (includeTenant) {
2156
+ const tenantFilterValue = this.getNodeParameter('cippApiTenantFilter', i);
2157
+ const tenantFilter = (0, GenericFunctions_1.getResourceLocatorValue)(tenantFilterValue);
2158
+ if (!query.tenantFilter) {
2159
+ query.tenantFilter = tenantFilter;
2160
+ }
2161
+ if (!body.tenantFilter) {
2162
+ body.tenantFilter = tenantFilter;
2163
+ }
2164
+ }
2165
+ const options = this.getNodeParameter('cippApiOptions', i, {});
2166
+ const maxPayloadBytes = Number(options.maxPayloadBytes ?? 262144);
2167
+ if (!Number.isFinite(maxPayloadBytes) || maxPayloadBytes <= 0) {
2168
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Max Payload Bytes must be a positive number.', { itemIndex: i });
2169
+ }
2170
+ const payloadBytes = new TextEncoder().encode(JSON.stringify(body)).length;
2171
+ if (payloadBytes > maxPayloadBytes) {
2172
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Payload is ${payloadBytes} bytes, which exceeds Max Payload Bytes (${maxPayloadBytes}).`, { itemIndex: i });
2173
+ }
2174
+ responseData = await GenericFunctions_1.cippApiRequest.call(this, method, endpoint, body, query);
2175
+ }
2026
2176
  else if (operation === 'graphRequest') {
2027
2177
  const tenantFilter = getTenantFilter();
2028
2178
  const endpoint = this.getNodeParameter('graphEndpoint', i);
@@ -2363,6 +2513,41 @@ class Cipp {
2363
2513
  responseData = responseData.slice(0, limit);
2364
2514
  }
2365
2515
  }
2516
+ else if (operation === 'listAppConsentRequests') {
2517
+ const returnAll = this.getNodeParameter('returnAll', i);
2518
+ const requestStatus = this.getNodeParameter('appConsentRequestStatus', i, '');
2519
+ const filter = this.getNodeParameter('appConsentFilter', i, '');
2520
+ const qs = { tenantFilter };
2521
+ if (requestStatus)
2522
+ qs.RequestStatus = requestStatus;
2523
+ if (filter)
2524
+ qs.Filter = filter;
2525
+ responseData = await GenericFunctions_1.cippApiRequest.call(this, 'GET', '/api/ListAppConsentRequests', {}, qs);
2526
+ if (Array.isArray(responseData) && !returnAll) {
2527
+ const limit = this.getNodeParameter('limit', i);
2528
+ responseData = responseData.slice(0, limit);
2529
+ }
2530
+ }
2531
+ else if (operation === 'listAzureAdConnectStatus') {
2532
+ const returnAll = this.getNodeParameter('returnAll', i);
2533
+ const dataToReturn = this.getNodeParameter('aadConnectDataToReturn', i, '');
2534
+ const qs = { tenantFilter };
2535
+ if (dataToReturn)
2536
+ qs.DataToReturn = dataToReturn;
2537
+ responseData = await GenericFunctions_1.cippApiRequest.call(this, 'GET', '/api/ListAzureADConnectStatus', {}, qs);
2538
+ if (Array.isArray(responseData) && !returnAll) {
2539
+ const limit = this.getNodeParameter('limit', i);
2540
+ responseData = responseData.slice(0, limit);
2541
+ }
2542
+ }
2543
+ else if (operation === 'listBasicAuth') {
2544
+ const returnAll = this.getNodeParameter('returnAll', i);
2545
+ responseData = await GenericFunctions_1.cippApiRequest.call(this, 'GET', '/api/ListBasicAuth', {}, { tenantFilter });
2546
+ if (Array.isArray(responseData) && !returnAll) {
2547
+ const limit = this.getNodeParameter('limit', i);
2548
+ responseData = responseData.slice(0, limit);
2549
+ }
2550
+ }
2366
2551
  else if (operation === 'listDeletedItems') {
2367
2552
  const returnAll = this.getNodeParameter('returnAll', i);
2368
2553
  responseData = await GenericFunctions_1.cippApiRequest.call(this, 'GET', '/api/ListDeletedItems', {}, { tenantFilter });
@@ -2371,6 +2556,14 @@ class Cipp {
2371
2556
  responseData = responseData.slice(0, limit);
2372
2557
  }
2373
2558
  }
2559
+ else if (operation === 'listDomains') {
2560
+ const returnAll = this.getNodeParameter('returnAll', i);
2561
+ responseData = await GenericFunctions_1.cippApiRequest.call(this, 'GET', '/api/ListDomains', {}, { tenantFilter });
2562
+ if (Array.isArray(responseData) && !returnAll) {
2563
+ const limit = this.getNodeParameter('limit', i);
2564
+ responseData = responseData.slice(0, limit);
2565
+ }
2566
+ }
2374
2567
  else if (operation === 'listRoles') {
2375
2568
  const returnAll = this.getNodeParameter('returnAll', i);
2376
2569
  responseData = await GenericFunctions_1.cippApiRequest.call(this, 'GET', '/api/ListRoles', {}, { tenantFilter });
@@ -2386,6 +2579,19 @@ class Cipp {
2386
2579
  ID: objectId,
2387
2580
  }, {});
2388
2581
  }
2582
+ else if (operation === 'setCloudManaged') {
2583
+ const objectId = this.getNodeParameter('cloudManagedObjectId', i);
2584
+ const displayName = this.getNodeParameter('cloudManagedDisplayName', i, '');
2585
+ const type = this.getNodeParameter('cloudManagedType', i);
2586
+ const isCloudManaged = this.getNodeParameter('isCloudManaged', i);
2587
+ responseData = await GenericFunctions_1.cippApiRequest.call(this, 'POST', '/api/ExecSetCloudManaged', {
2588
+ tenantFilter,
2589
+ displayName,
2590
+ ID: objectId,
2591
+ isCloudManaged: String(isCloudManaged),
2592
+ type,
2593
+ }, {});
2594
+ }
2389
2595
  }
2390
2596
  // ==================== POLICY ====================
2391
2597
  else if (resource === 'policy') {
@@ -2465,6 +2671,13 @@ class Cipp {
2465
2671
  responseData = responseData.slice(0, this.getNodeParameter('limit', i));
2466
2672
  }
2467
2673
  }
2674
+ else if (operation === 'listSpamFilterTemplates') {
2675
+ const returnAll = this.getNodeParameter('returnAll', i);
2676
+ responseData = await GenericFunctions_1.cippApiRequest.call(this, 'GET', '/api/ListSpamFilterTemplates', {}, { tenantFilter });
2677
+ if (Array.isArray(responseData) && !returnAll) {
2678
+ responseData = responseData.slice(0, this.getNodeParameter('limit', i));
2679
+ }
2680
+ }
2468
2681
  else if (operation === 'addSpamFilter') {
2469
2682
  const policyJson = this.getNodeParameter('esSpamFilterJson', i);
2470
2683
  let policyData;