n8n-nodes-jmap 0.2.6 → 0.3.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.
@@ -0,0 +1,13 @@
1
+ import type { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties, Icon } from 'n8n-workflow';
2
+ /**
3
+ * JMAP API Credentials for Basic Auth authentication
4
+ */
5
+ export declare class JmapBasicAuthApi implements ICredentialType {
6
+ name: string;
7
+ displayName: string;
8
+ documentationUrl: string;
9
+ icon: Icon;
10
+ properties: INodeProperties[];
11
+ authenticate: IAuthenticateGeneric;
12
+ test: ICredentialTestRequest;
13
+ }
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JmapBasicAuthApi = void 0;
4
+ /**
5
+ * JMAP API Credentials for Basic Auth authentication
6
+ */
7
+ class JmapBasicAuthApi {
8
+ constructor() {
9
+ this.name = 'jmapBasicAuthApi';
10
+ this.displayName = 'JMAP Basic Auth API';
11
+ this.documentationUrl = 'https://jmap.io/spec-core.html';
12
+ this.icon = {
13
+ light: 'file:../nodes/Jmap/jmap.svg',
14
+ dark: 'file:../nodes/Jmap/jmap.svg',
15
+ };
16
+ this.properties = [
17
+ {
18
+ displayName: 'JMAP Server URL',
19
+ name: 'serverUrl',
20
+ type: 'string',
21
+ default: 'https://jmap.example.com/jmap',
22
+ placeholder: 'https://jmap.example.com/jmap',
23
+ description: 'The base URL of the JMAP server',
24
+ required: true,
25
+ },
26
+ {
27
+ displayName: 'Email',
28
+ name: 'email',
29
+ type: 'string',
30
+ placeholder: 'user@example.com',
31
+ default: '',
32
+ required: true,
33
+ },
34
+ {
35
+ displayName: 'Password',
36
+ name: 'password',
37
+ type: 'string',
38
+ typeOptions: {
39
+ password: true,
40
+ },
41
+ default: '',
42
+ required: true,
43
+ },
44
+ ];
45
+ this.authenticate = {
46
+ type: 'generic',
47
+ properties: {
48
+ auth: {
49
+ username: '={{$credentials.email}}',
50
+ password: '={{$credentials.password}}',
51
+ },
52
+ },
53
+ };
54
+ this.test = {
55
+ request: {
56
+ baseURL: '={{$credentials.serverUrl}}',
57
+ url: '/session',
58
+ method: 'GET',
59
+ headers: {
60
+ Accept: 'application/json',
61
+ },
62
+ },
63
+ };
64
+ }
65
+ }
66
+ exports.JmapBasicAuthApi = JmapBasicAuthApi;
@@ -0,0 +1,13 @@
1
+ import type { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties, Icon } from 'n8n-workflow';
2
+ /**
3
+ * JMAP API Credentials for Bearer Token authentication
4
+ */
5
+ export declare class JmapBearerTokenApi implements ICredentialType {
6
+ name: string;
7
+ displayName: string;
8
+ documentationUrl: string;
9
+ icon: Icon;
10
+ properties: INodeProperties[];
11
+ authenticate: IAuthenticateGeneric;
12
+ test: ICredentialTestRequest;
13
+ }
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JmapBearerTokenApi = void 0;
4
+ /**
5
+ * JMAP API Credentials for Bearer Token authentication
6
+ */
7
+ class JmapBearerTokenApi {
8
+ constructor() {
9
+ this.name = 'jmapBearerTokenApi';
10
+ this.displayName = 'JMAP Bearer Token API';
11
+ this.documentationUrl = 'https://jmap.io/spec-core.html';
12
+ this.icon = {
13
+ light: 'file:../nodes/Jmap/jmap.svg',
14
+ dark: 'file:../nodes/Jmap/jmap.svg',
15
+ };
16
+ this.properties = [
17
+ {
18
+ displayName: 'JMAP Server URL',
19
+ name: 'serverUrl',
20
+ type: 'string',
21
+ default: 'https://jmap.example.com/jmap',
22
+ placeholder: 'https://jmap.example.com/jmap',
23
+ description: 'The base URL of the JMAP server',
24
+ required: true,
25
+ },
26
+ {
27
+ displayName: 'Access Token',
28
+ name: 'accessToken',
29
+ type: 'string',
30
+ typeOptions: {
31
+ password: true,
32
+ },
33
+ default: '',
34
+ required: true,
35
+ description: 'The access token (e.g., from OAuth2/OIDC)',
36
+ },
37
+ ];
38
+ this.authenticate = {
39
+ type: 'generic',
40
+ properties: {
41
+ headers: {
42
+ Authorization: '=Bearer {{$credentials.accessToken}}',
43
+ },
44
+ },
45
+ };
46
+ this.test = {
47
+ request: {
48
+ baseURL: '={{$credentials.serverUrl}}',
49
+ url: '/session',
50
+ method: 'GET',
51
+ headers: {
52
+ Accept: 'application/json',
53
+ },
54
+ },
55
+ };
56
+ }
57
+ }
58
+ exports.JmapBearerTokenApi = JmapBearerTokenApi;
@@ -11,17 +11,4 @@ export declare class JmapOAuth2Api implements ICredentialType {
11
11
  extends: string[];
12
12
  icon: Icon;
13
13
  properties: INodeProperties[];
14
- oauth2: {
15
- tokenExpiredStatusCode: number;
16
- grantType: string;
17
- scope: string;
18
- tokenRequestMethod: "POST";
19
- authorizeUrl: {
20
- url: string;
21
- };
22
- accessTokenUrl: {
23
- url: string;
24
- };
25
- clientAuthentication: "body";
26
- };
27
14
  }
@@ -88,16 +88,6 @@ class JmapOAuth2Api {
88
88
  default: 'body',
89
89
  },
90
90
  ];
91
- // OAuth2 flow configuration
92
- this.oauth2 = {
93
- tokenExpiredStatusCode: 401,
94
- grantType: 'pkce',
95
- scope: 'openid email profile offline_access',
96
- tokenRequestMethod: 'POST',
97
- authorizeUrl: { url: '={{ $credentials.authUrl }}' },
98
- accessTokenUrl: { url: '={{ $credentials.accessTokenUrl }}' },
99
- clientAuthentication: 'body',
100
- };
101
91
  }
102
92
  }
103
93
  exports.JmapOAuth2Api = JmapOAuth2Api;
@@ -52,7 +52,8 @@ async function getServerUrl(context) {
52
52
  return credentials.jmapServerUrl.replace(/\/$/, '');
53
53
  }
54
54
  else {
55
- const credentials = await context.getCredentials('jmapApi');
55
+ // Both jmapBasicAuthApi and jmapBearerTokenApi use 'serverUrl'
56
+ const credentials = await context.getCredentials(authType);
56
57
  return credentials.serverUrl.replace(/\/$/, '');
57
58
  }
58
59
  }
@@ -63,45 +64,18 @@ async function makeJmapRequest(context, method, endpoint, body) {
63
64
  const authType = getAuthType(context);
64
65
  const serverUrl = await getServerUrl(context);
65
66
  const url = endpoint.startsWith('http') ? endpoint : `${serverUrl}${endpoint}`;
66
- if (authType === 'jmapOAuth2Api') {
67
- // Use n8n's built-in OAuth2 authentication
68
- const response = await context.helpers.httpRequestWithAuthentication.call(context, 'jmapOAuth2Api', {
69
- method,
70
- url,
71
- headers: {
72
- 'Content-Type': 'application/json',
73
- Accept: 'application/json',
74
- },
75
- body,
76
- json: true,
77
- });
78
- return response;
79
- }
80
- else {
81
- // Use Basic Auth or Bearer Token
82
- const credentials = await context.getCredentials('jmapApi');
83
- const authMethod = credentials.authMethod || 'basicAuth';
84
- const headers = {
67
+ const requestOptions = {
68
+ method,
69
+ url,
70
+ headers: {
85
71
  'Content-Type': 'application/json',
86
72
  Accept: 'application/json',
87
- };
88
- if (authMethod === 'basicAuth') {
89
- const authString = Buffer.from(`${credentials.email}:${credentials.password}`).toString('base64');
90
- headers.Authorization = `Basic ${authString}`;
91
- }
92
- else if (authMethod === 'bearerToken') {
93
- headers.Authorization = `Bearer ${credentials.accessToken}`;
94
- }
95
- const options = {
96
- method,
97
- url,
98
- headers,
99
- body,
100
- json: true,
101
- };
102
- const response = await context.helpers.httpRequest(options);
103
- return response;
104
- }
73
+ },
74
+ body,
75
+ json: true,
76
+ };
77
+ const response = await context.helpers.httpRequestWithAuthentication.call(context, authType, requestOptions);
78
+ return response;
105
79
  }
106
80
  /**
107
81
  * Get JMAP session from the server
@@ -148,7 +122,7 @@ async function getPrimaryAccountId() {
148
122
  if (accountIds.length > 0) {
149
123
  return accountIds[0];
150
124
  }
151
- throw new Error('No JMAP account found');
125
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No JMAP account found');
152
126
  }
153
127
  /**
154
128
  * Get all mailboxes for an account
@@ -159,7 +133,7 @@ async function getMailboxes(accountId) {
159
133
  if (methodResponse[0] === 'Mailbox/get') {
160
134
  return methodResponse[1].list;
161
135
  }
162
- throw new Error('Failed to get mailboxes');
136
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to get mailboxes');
163
137
  }
164
138
  /**
165
139
  * Find a mailbox by name
@@ -194,7 +168,7 @@ async function queryEmails(accountId, filter = {}, sort = [{ property: 'received
194
168
  total: result.total,
195
169
  };
196
170
  }
197
- throw new Error('Failed to query emails');
171
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to query emails');
198
172
  }
199
173
  /**
200
174
  * Get emails by IDs
@@ -223,7 +197,7 @@ async function getEmails(accountId, ids, properties = [
223
197
  if (methodResponse[0] === 'Email/get') {
224
198
  return methodResponse[1].list;
225
199
  }
226
- throw new Error('Failed to get emails');
200
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to get emails');
227
201
  }
228
202
  /**
229
203
  * Create and send an email
@@ -231,7 +205,7 @@ async function getEmails(accountId, ids, properties = [
231
205
  async function sendEmail(accountId, email, identityId) {
232
206
  const draftsMailbox = await findMailboxByRole.call(this, accountId, 'drafts');
233
207
  if (!draftsMailbox) {
234
- throw new Error('Drafts mailbox not found');
208
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Drafts mailbox not found');
235
209
  }
236
210
  const emailCreate = {
237
211
  ...email,
@@ -252,7 +226,7 @@ async function sendEmail(accountId, email, identityId) {
252
226
  ], [exports.JMAP_CAPABILITIES.CORE, exports.JMAP_CAPABILITIES.MAIL, exports.JMAP_CAPABILITIES.SUBMISSION]);
253
227
  for (const methodResponse of response.methodResponses) {
254
228
  if (methodResponse[0] === 'error') {
255
- throw new Error(`JMAP error: ${JSON.stringify(methodResponse[1])}`);
229
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `JMAP error: ${JSON.stringify(methodResponse[1])}`);
256
230
  }
257
231
  }
258
232
  return response.methodResponses[1][1];
@@ -263,7 +237,7 @@ async function sendEmail(accountId, email, identityId) {
263
237
  async function createDraft(accountId, email) {
264
238
  const draftsMailbox = await findMailboxByRole.call(this, accountId, 'drafts');
265
239
  if (!draftsMailbox) {
266
- throw new Error('Drafts mailbox not found');
240
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Drafts mailbox not found');
267
241
  }
268
242
  const emailCreate = {
269
243
  ...email,
@@ -273,7 +247,7 @@ async function createDraft(accountId, email) {
273
247
  const response = await jmapApiRequest.call(this, [['Email/set', { accountId, create: { draft: emailCreate } }, 'c1']]);
274
248
  const methodResponse = response.methodResponses[0];
275
249
  if (methodResponse[0] === 'error') {
276
- throw new Error(`JMAP error: ${JSON.stringify(methodResponse[1])}`);
250
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `JMAP error: ${JSON.stringify(methodResponse[1])}`);
277
251
  }
278
252
  if (methodResponse[0] === 'Email/set') {
279
253
  const result = methodResponse[1];
@@ -293,7 +267,7 @@ async function getIdentities(accountId) {
293
267
  if (methodResponse[0] === 'Identity/get') {
294
268
  return methodResponse[1].list;
295
269
  }
296
- throw new Error('Failed to get identities');
270
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to get identities');
297
271
  }
298
272
  /**
299
273
  * Update email keywords
@@ -304,7 +278,7 @@ async function updateEmailKeywords(accountId, emailId, keywords) {
304
278
  if (methodResponse[0] === 'Email/set') {
305
279
  return methodResponse[1];
306
280
  }
307
- throw new Error('Failed to update email');
281
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to update email');
308
282
  }
309
283
  /**
310
284
  * Move email to a different mailbox
@@ -324,7 +298,7 @@ async function moveEmail(accountId, emailId, targetMailboxId) {
324
298
  if (methodResponse[0] === 'Email/set') {
325
299
  return methodResponse[1];
326
300
  }
327
- throw new Error('Failed to move email');
301
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to move email');
328
302
  }
329
303
  /**
330
304
  * Add a label (mailbox) to an email
@@ -344,7 +318,7 @@ async function addLabel(accountId, emailId, mailboxId) {
344
318
  if (methodResponse[0] === 'Email/set') {
345
319
  return methodResponse[1];
346
320
  }
347
- throw new Error('Failed to add label');
321
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to add label');
348
322
  }
349
323
  /**
350
324
  * Remove a label (mailbox) from an email
@@ -364,7 +338,7 @@ async function removeLabel(accountId, emailId, mailboxId) {
364
338
  if (methodResponse[0] === 'Email/set') {
365
339
  return methodResponse[1];
366
340
  }
367
- throw new Error('Failed to remove label');
341
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to remove label');
368
342
  }
369
343
  /**
370
344
  * Get labels (mailboxes) for an email with their names
@@ -372,7 +346,7 @@ async function removeLabel(accountId, emailId, mailboxId) {
372
346
  async function getLabels(accountId, emailId) {
373
347
  const emails = await getEmails.call(this, accountId, [emailId], ['id', 'mailboxIds']);
374
348
  if (emails.length === 0) {
375
- throw new Error('Email not found');
349
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Email not found');
376
350
  }
377
351
  const email = emails[0];
378
352
  const mailboxIds = email.mailboxIds;
@@ -407,7 +381,7 @@ async function deleteEmails(accountId, emailIds) {
407
381
  if (methodResponse[0] === 'Email/set') {
408
382
  return methodResponse[1];
409
383
  }
410
- throw new Error('Failed to delete emails');
384
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to delete emails');
411
385
  }
412
386
  /**
413
387
  * Get threads
@@ -418,7 +392,7 @@ async function getThreads(accountId, ids) {
418
392
  if (methodResponse[0] === 'Thread/get') {
419
393
  return methodResponse[1].list;
420
394
  }
421
- throw new Error('Failed to get threads');
395
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to get threads');
422
396
  }
423
397
  /**
424
398
  * Download an attachment blob
@@ -431,34 +405,12 @@ async function downloadBlob(accountId, blobId, name, type) {
431
405
  .replace('{blobId}', blobId)
432
406
  .replace('{name}', encodeURIComponent(name))
433
407
  .replace('{type}', encodeURIComponent(type));
434
- if (authType === 'jmapOAuth2Api') {
435
- const response = await this.helpers.httpRequestWithAuthentication.call(this, 'jmapOAuth2Api', {
436
- method: 'GET',
437
- url: downloadUrl,
438
- encoding: 'arraybuffer',
439
- });
440
- return Buffer.from(response);
441
- }
442
- else {
443
- const credentials = await this.getCredentials('jmapApi');
444
- const authMethod = credentials.authMethod || 'basicAuth';
445
- const headers = {};
446
- if (authMethod === 'basicAuth') {
447
- const authString = Buffer.from(`${credentials.email}:${credentials.password}`).toString('base64');
448
- headers.Authorization = `Basic ${authString}`;
449
- }
450
- else if (authMethod === 'bearerToken') {
451
- headers.Authorization = `Bearer ${credentials.accessToken}`;
452
- }
453
- const options = {
454
- method: 'GET',
455
- url: downloadUrl,
456
- headers,
457
- encoding: 'arraybuffer',
458
- };
459
- const response = await this.helpers.httpRequest(options);
460
- return Buffer.from(response);
461
- }
408
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, authType, {
409
+ method: 'GET',
410
+ url: downloadUrl,
411
+ encoding: 'arraybuffer',
412
+ });
413
+ return Buffer.from(response);
462
414
  }
463
415
  /**
464
416
  * Check if a MIME type matches a filter pattern
@@ -486,7 +438,7 @@ async function getAttachments(accountId, emailId, options = {}) {
486
438
  'attachments',
487
439
  ]);
488
440
  if (emails.length === 0) {
489
- throw new Error(`Email with ID ${emailId} not found`);
441
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Email with ID ${emailId} not found`);
490
442
  }
491
443
  const email = emails[0];
492
444
  const attachments = email.attachments || [];
@@ -18,15 +18,24 @@ class Jmap {
18
18
  defaults: {
19
19
  name: 'JMAP',
20
20
  },
21
- inputs: ['main'],
22
- outputs: ['main'],
21
+ inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
22
+ outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
23
23
  credentials: [
24
24
  {
25
- name: 'jmapApi',
25
+ name: 'jmapBasicAuthApi',
26
26
  required: true,
27
27
  displayOptions: {
28
28
  show: {
29
- authentication: ['jmapApi'],
29
+ authentication: ['jmapBasicAuthApi'],
30
+ },
31
+ },
32
+ },
33
+ {
34
+ name: 'jmapBearerTokenApi',
35
+ required: true,
36
+ displayOptions: {
37
+ show: {
38
+ authentication: ['jmapBearerTokenApi'],
30
39
  },
31
40
  },
32
41
  },
@@ -52,8 +61,12 @@ class Jmap {
52
61
  value: 'jmapOAuth2Api',
53
62
  },
54
63
  {
55
- name: 'Basic Auth / Bearer Token',
56
- value: 'jmapApi',
64
+ name: 'Basic Auth',
65
+ value: 'jmapBasicAuthApi',
66
+ },
67
+ {
68
+ name: 'Bearer Token',
69
+ value: 'jmapBearerTokenApi',
57
70
  },
58
71
  ],
59
72
  default: 'jmapOAuth2Api',
@@ -608,7 +621,12 @@ class Jmap {
608
621
  const resource = this.getNodeParameter('resource', 0);
609
622
  const operation = this.getNodeParameter('operation', 0);
610
623
  const accountId = await GenericFunctions_1.getPrimaryAccountId.call(this);
611
- for (let i = 0; i < items.length; i++) {
624
+ // Operations that should only run once, regardless of input items
625
+ const singleExecutionOperations = [
626
+ 'getMany', // Email/Mailbox/Thread getMany - query with filters, not per-item
627
+ ];
628
+ const itemsToProcess = singleExecutionOperations.includes(operation) ? 1 : items.length;
629
+ for (let i = 0; i < itemsToProcess; i++) {
612
630
  try {
613
631
  let responseData = {};
614
632
  // ==================== EMAIL ====================
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.JmapTrigger = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
4
5
  const GenericFunctions_1 = require("./GenericFunctions");
5
6
  class JmapTrigger {
6
7
  constructor() {
@@ -16,14 +17,23 @@ class JmapTrigger {
16
17
  name: 'JMAP Trigger',
17
18
  },
18
19
  inputs: [],
19
- outputs: ['main'],
20
+ outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
20
21
  credentials: [
21
22
  {
22
- name: 'jmapApi',
23
+ name: 'jmapBasicAuthApi',
23
24
  required: true,
24
25
  displayOptions: {
25
26
  show: {
26
- authentication: ['jmapApi'],
27
+ authentication: ['jmapBasicAuthApi'],
28
+ },
29
+ },
30
+ },
31
+ {
32
+ name: 'jmapBearerTokenApi',
33
+ required: true,
34
+ displayOptions: {
35
+ show: {
36
+ authentication: ['jmapBearerTokenApi'],
27
37
  },
28
38
  },
29
39
  },
@@ -50,8 +60,12 @@ class JmapTrigger {
50
60
  value: 'jmapOAuth2Api',
51
61
  },
52
62
  {
53
- name: 'Basic Auth / Bearer Token',
54
- value: 'jmapApi',
63
+ name: 'Basic Auth',
64
+ value: 'jmapBasicAuthApi',
65
+ },
66
+ {
67
+ name: 'Bearer Token',
68
+ value: 'jmapBearerTokenApi',
55
69
  },
56
70
  ],
57
71
  default: 'jmapOAuth2Api',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-jmap",
3
- "version": "0.2.6",
3
+ "version": "0.3.0",
4
4
  "description": "n8n community node for JMAP email protocol (RFC 8620/8621) - Works with Apache James, Twake Mail, Fastmail, and other JMAP-compatible servers",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",
@@ -38,7 +38,8 @@
38
38
  "n8n": {
39
39
  "n8nNodesApiVersion": 1,
40
40
  "credentials": [
41
- "dist/credentials/JmapApi.credentials.js",
41
+ "dist/credentials/JmapBasicAuthApi.credentials.js",
42
+ "dist/credentials/JmapBearerTokenApi.credentials.js",
42
43
  "dist/credentials/JmapOAuth2Api.credentials.js"
43
44
  ],
44
45
  "nodes": [
@@ -1,13 +0,0 @@
1
- import { ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
2
- /**
3
- * JMAP API Credentials for Basic Auth or Bearer Token authentication
4
- *
5
- * For OAuth2/OIDC with LemonLDAP, use the JmapOAuth2Api credentials instead.
6
- */
7
- export declare class JmapApi implements ICredentialType {
8
- name: string;
9
- displayName: string;
10
- documentationUrl: string;
11
- properties: INodeProperties[];
12
- test: ICredentialTestRequest;
13
- }
@@ -1,105 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.JmapApi = void 0;
4
- /**
5
- * JMAP API Credentials for Basic Auth or Bearer Token authentication
6
- *
7
- * For OAuth2/OIDC with LemonLDAP, use the JmapOAuth2Api credentials instead.
8
- */
9
- class JmapApi {
10
- constructor() {
11
- this.name = 'jmapApi';
12
- this.displayName = 'JMAP API';
13
- this.documentationUrl = 'https://jmap.io/spec-core.html';
14
- this.properties = [
15
- {
16
- displayName: 'JMAP Server URL',
17
- name: 'serverUrl',
18
- type: 'string',
19
- default: 'https://jmap.example.com/jmap',
20
- placeholder: 'https://jmap.example.com/jmap',
21
- description: 'The base URL of the JMAP server',
22
- required: true,
23
- },
24
- {
25
- displayName: 'Authentication Method',
26
- name: 'authMethod',
27
- type: 'options',
28
- options: [
29
- {
30
- name: 'Basic Auth',
31
- value: 'basicAuth',
32
- description: 'Authenticate with email and password',
33
- },
34
- {
35
- name: 'Bearer Token',
36
- value: 'bearerToken',
37
- description: 'Authenticate with an existing access token',
38
- },
39
- ],
40
- default: 'basicAuth',
41
- },
42
- // Basic Auth fields
43
- {
44
- displayName: 'Email',
45
- name: 'email',
46
- type: 'string',
47
- placeholder: 'user@example.com',
48
- default: '',
49
- required: true,
50
- displayOptions: {
51
- show: {
52
- authMethod: ['basicAuth'],
53
- },
54
- },
55
- },
56
- {
57
- displayName: 'Password',
58
- name: 'password',
59
- type: 'string',
60
- typeOptions: {
61
- password: true,
62
- },
63
- default: '',
64
- required: true,
65
- displayOptions: {
66
- show: {
67
- authMethod: ['basicAuth'],
68
- },
69
- },
70
- },
71
- // Bearer Token field
72
- {
73
- displayName: 'Access Token',
74
- name: 'accessToken',
75
- type: 'string',
76
- typeOptions: {
77
- password: true,
78
- },
79
- default: '',
80
- required: true,
81
- description: 'The access token (e.g., from OAuth2/OIDC)',
82
- displayOptions: {
83
- show: {
84
- authMethod: ['bearerToken'],
85
- },
86
- },
87
- },
88
- ];
89
- this.test = {
90
- request: {
91
- baseURL: '={{$credentials.serverUrl}}',
92
- url: '/session',
93
- method: 'GET',
94
- headers: {
95
- Accept: 'application/json',
96
- },
97
- auth: {
98
- username: '={{$credentials.email}}',
99
- password: '={{$credentials.password}}',
100
- },
101
- },
102
- };
103
- }
104
- }
105
- exports.JmapApi = JmapApi;