emailengine-app 2.69.0 → 2.71.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/.github/workflows/deploy.yml +6 -3
- package/.github/workflows/release.yaml +2 -0
- package/.github/workflows/test.yml +73 -12
- package/.ncurc.js +3 -3
- package/CHANGELOG.md +37 -0
- package/Gruntfile.js +21 -23
- package/bin/emailengine.js +8 -1
- package/config/default.toml +5 -0
- package/config/test.toml +5 -0
- package/data/google-crawlers.json +1 -1
- package/getswagger.sh +44 -4
- package/gettext-extract.js +163 -0
- package/lib/account.js +104 -72
- package/lib/api-routes/account-routes.js +231 -71
- package/lib/api-routes/blocklist-routes.js +25 -18
- package/lib/api-routes/chat-routes.js +32 -14
- package/lib/api-routes/delivery-test-routes.js +30 -5
- package/lib/api-routes/export-routes.js +27 -2
- package/lib/api-routes/gateway-routes.js +63 -12
- package/lib/api-routes/license-routes.js +18 -4
- package/lib/api-routes/mailbox-routes.js +33 -7
- package/lib/api-routes/message-routes.js +291 -145
- package/lib/api-routes/oauth2-app-routes.js +90 -24
- package/lib/api-routes/outbox-routes.js +16 -4
- package/lib/api-routes/pubsub-routes.js +8 -4
- package/lib/api-routes/route-helpers.js +14 -1
- package/lib/api-routes/settings-routes.js +51 -25
- package/lib/api-routes/stats-routes.js +37 -3
- package/lib/api-routes/submit-routes.js +31 -42
- package/lib/api-routes/template-routes.js +54 -21
- package/lib/api-routes/token-routes.js +67 -67
- package/lib/api-routes/webhook-route-routes.js +37 -8
- package/lib/autodetect-imap-settings.js +0 -2
- package/lib/consts.js +5 -0
- package/lib/document-store.js +22 -1
- package/lib/email-client/base-client.js +31 -8
- package/lib/email-client/gmail-client.js +119 -112
- package/lib/email-client/imap/mailbox.js +2 -2
- package/lib/email-client/imap/subconnection.js +0 -1
- package/lib/email-client/imap/sync-operations.js +1 -1
- package/lib/email-client/imap-client.js +36 -17
- package/lib/email-client/notification-handler.js +3 -6
- package/lib/email-client/outlook-client.js +49 -62
- package/lib/export.js +49 -1
- package/lib/feature-flags.js +8 -2
- package/lib/gateway.js +4 -9
- package/lib/get-raw-email.js +5 -5
- package/lib/imapproxy/imap-core/lib/imap-connection.js +0 -1
- package/lib/license-beacon.js +367 -0
- package/lib/logger.js +35 -22
- package/lib/metrics-collector.js +0 -2
- package/lib/oauth2-apps.js +13 -4
- package/lib/outbox.js +24 -40
- package/lib/redis-operations.js +1 -1
- package/lib/routes-ui.js +2 -1
- package/lib/schemas.js +403 -83
- package/lib/sentry.js +139 -0
- package/lib/settings.js +9 -3
- package/lib/stream-encrypt.js +1 -1
- package/lib/templates.js +1 -1
- package/lib/tokens.js +5 -3
- package/lib/tools.js +28 -6
- package/lib/ui-routes/account-routes.js +7 -4
- package/lib/ui-routes/admin-config-routes.js +20 -6
- package/lib/ui-routes/document-store-routes.js +7 -1
- package/lib/ui-routes/oauth-config-routes.js +0 -2
- package/lib/ui-routes/route-helpers.js +0 -2
- package/lib/ui-routes/unsubscribe-routes.js +0 -2
- package/lib/webhooks.js +8 -4
- package/package.json +23 -19
- package/sbom.json +1 -1
- package/server.js +38 -31
- package/static/licenses.html +171 -391
- package/translations/de.mo +0 -0
- package/translations/de.po +154 -142
- package/translations/et.mo +0 -0
- package/translations/et.po +129 -131
- package/translations/fr.mo +0 -0
- package/translations/fr.po +133 -136
- package/translations/ja.mo +0 -0
- package/translations/ja.po +126 -129
- package/translations/messages.pot +107 -107
- package/translations/nl.mo +0 -0
- package/translations/nl.po +128 -130
- package/translations/pl.mo +0 -0
- package/translations/pl.po +125 -128
- package/update-info.sh +19 -1
- package/views/config/logging.hbs +48 -0
- package/views/dashboard.hbs +22 -0
- package/workers/api.js +33 -37
- package/workers/documents.js +2 -22
- package/workers/export.js +73 -92
- package/workers/imap-proxy.js +3 -23
- package/workers/imap.js +2 -22
- package/workers/smtp.js +2 -22
- package/workers/submit.js +6 -24
- package/workers/webhooks.js +2 -22
package/lib/account.js
CHANGED
|
@@ -20,6 +20,7 @@ const { deepStrictEqual, strictEqual } = require('assert');
|
|
|
20
20
|
const { encrypt, decrypt } = require('./encrypt');
|
|
21
21
|
const { oauth2Apps, LEGACY_KEYS, isApiBasedApp } = require('./oauth2-apps');
|
|
22
22
|
const settings = require('./settings');
|
|
23
|
+
const { isDocumentStoreEnabled, documentStoreFeatureEnabled } = require('./document-store');
|
|
23
24
|
const redisScanDelete = require('./redis-scan-delete');
|
|
24
25
|
const { customAlphabet } = require('nanoid');
|
|
25
26
|
const Lock = require('ioredfour');
|
|
@@ -945,7 +946,7 @@ class Account {
|
|
|
945
946
|
throw error;
|
|
946
947
|
}
|
|
947
948
|
|
|
948
|
-
let state
|
|
949
|
+
let state;
|
|
949
950
|
if (result[0][1] && result[0][1].account) {
|
|
950
951
|
// existing user
|
|
951
952
|
state = 'existing';
|
|
@@ -1048,28 +1049,33 @@ class Account {
|
|
|
1048
1049
|
};
|
|
1049
1050
|
}
|
|
1050
1051
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1052
|
+
// Only notify the documents queue when the deprecated Document Store feature is enabled.
|
|
1053
|
+
// When it is off the documents worker is not running, so an enqueued job would never be
|
|
1054
|
+
// consumed and would pile up in Redis.
|
|
1055
|
+
if (documentStoreFeatureEnabled) {
|
|
1056
|
+
try {
|
|
1057
|
+
let queueKeep = (await settings.get('queueKeep')) || true;
|
|
1058
|
+
let serviceUrl = (await settings.get('serviceUrl')) || null;
|
|
1054
1059
|
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1060
|
+
let payload = {
|
|
1061
|
+
serviceUrl,
|
|
1062
|
+
account: this.account,
|
|
1063
|
+
date: new Date().toISOString(),
|
|
1064
|
+
event: ACCOUNT_DELETED_NOTIFY
|
|
1065
|
+
};
|
|
1061
1066
|
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1067
|
+
await this.documentsQueue.add(ACCOUNT_DELETED_NOTIFY, payload, {
|
|
1068
|
+
removeOnComplete: queueKeep,
|
|
1069
|
+
removeOnFail: queueKeep,
|
|
1070
|
+
attempts: 10,
|
|
1071
|
+
backoff: {
|
|
1072
|
+
type: 'exponential',
|
|
1073
|
+
delay: 5000
|
|
1074
|
+
}
|
|
1075
|
+
});
|
|
1076
|
+
} catch (err) {
|
|
1077
|
+
this.logger.error({ msg: 'Failed to add entry to documents queue', err });
|
|
1078
|
+
}
|
|
1073
1079
|
}
|
|
1074
1080
|
|
|
1075
1081
|
await this.call({
|
|
@@ -1267,16 +1273,7 @@ class Account {
|
|
|
1267
1273
|
} catch (err) {
|
|
1268
1274
|
// should not happen
|
|
1269
1275
|
if (logger.notifyError) {
|
|
1270
|
-
logger.notifyError(err,
|
|
1271
|
-
if (this.account) {
|
|
1272
|
-
event.setUser(this.account);
|
|
1273
|
-
}
|
|
1274
|
-
|
|
1275
|
-
event.addMetadata('ee', {
|
|
1276
|
-
path,
|
|
1277
|
-
mailboxListing: typeof mailboxListing
|
|
1278
|
-
});
|
|
1279
|
-
});
|
|
1276
|
+
logger.notifyError(err, { user: this.account, meta: { path, mailboxListing: typeof mailboxListing } });
|
|
1280
1277
|
}
|
|
1281
1278
|
|
|
1282
1279
|
let message = 'Failed to process stored mailbox listing';
|
|
@@ -1290,22 +1287,44 @@ class Account {
|
|
|
1290
1287
|
return mailboxes;
|
|
1291
1288
|
}
|
|
1292
1289
|
|
|
1290
|
+
// Worker backends return false for entities they can not find (e.g. an unknown mailbox path
|
|
1291
|
+
// or message ID on IMAP). Convert such results into a 404 error for the API.
|
|
1292
|
+
assertFound(result, message, code) {
|
|
1293
|
+
if (!result) {
|
|
1294
|
+
let error = Boom.boomify(new Error(message), { statusCode: 404 });
|
|
1295
|
+
error.output.payload.code = code;
|
|
1296
|
+
throw error;
|
|
1297
|
+
}
|
|
1298
|
+
return result;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
assertMessageFound(result) {
|
|
1302
|
+
return this.assertFound(result, 'Requested message was not found', 'MessageNotFound');
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
assertFolderFound(result) {
|
|
1306
|
+
return this.assertFound(result, 'Requested mailbox folder was not found', 'FolderNotFound');
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1293
1309
|
async updateMessage(message, updates) {
|
|
1294
1310
|
await this.loadAccountData(this.account, true);
|
|
1295
1311
|
|
|
1296
|
-
|
|
1312
|
+
let result = await this.call({
|
|
1297
1313
|
cmd: 'updateMessage',
|
|
1298
1314
|
account: this.account,
|
|
1299
1315
|
message,
|
|
1300
1316
|
updates,
|
|
1301
1317
|
timeout: this.timeout
|
|
1302
1318
|
});
|
|
1319
|
+
|
|
1320
|
+
// IMAP backend returns false for unknown messages and folders
|
|
1321
|
+
return this.assertMessageFound(result);
|
|
1303
1322
|
}
|
|
1304
1323
|
|
|
1305
1324
|
async updateMessages(path, search, updates) {
|
|
1306
1325
|
await this.loadAccountData(this.account, true);
|
|
1307
1326
|
|
|
1308
|
-
|
|
1327
|
+
let result = await this.call({
|
|
1309
1328
|
cmd: 'updateMessages',
|
|
1310
1329
|
account: this.account,
|
|
1311
1330
|
path,
|
|
@@ -1313,6 +1332,9 @@ class Account {
|
|
|
1313
1332
|
updates,
|
|
1314
1333
|
timeout: this.timeout
|
|
1315
1334
|
});
|
|
1335
|
+
|
|
1336
|
+
// IMAP backend returns false for unknown folders
|
|
1337
|
+
return this.assertFolderFound(result);
|
|
1316
1338
|
}
|
|
1317
1339
|
|
|
1318
1340
|
async listMailboxes(query) {
|
|
@@ -1335,7 +1357,8 @@ class Account {
|
|
|
1335
1357
|
|
|
1336
1358
|
async moveMessage(message, target, options) {
|
|
1337
1359
|
await this.loadAccountData(this.account, true);
|
|
1338
|
-
|
|
1360
|
+
|
|
1361
|
+
let result = await this.call({
|
|
1339
1362
|
cmd: 'moveMessage',
|
|
1340
1363
|
account: this.account,
|
|
1341
1364
|
message,
|
|
@@ -1343,11 +1366,15 @@ class Account {
|
|
|
1343
1366
|
options,
|
|
1344
1367
|
timeout: this.timeout
|
|
1345
1368
|
});
|
|
1369
|
+
|
|
1370
|
+
// IMAP backend returns false for unknown messages and folders
|
|
1371
|
+
return this.assertMessageFound(result);
|
|
1346
1372
|
}
|
|
1347
1373
|
|
|
1348
1374
|
async moveMessages(source, search, target) {
|
|
1349
1375
|
await this.loadAccountData(this.account, true);
|
|
1350
|
-
|
|
1376
|
+
|
|
1377
|
+
let result = await this.call({
|
|
1351
1378
|
cmd: 'moveMessages',
|
|
1352
1379
|
account: this.account,
|
|
1353
1380
|
source,
|
|
@@ -1355,24 +1382,30 @@ class Account {
|
|
|
1355
1382
|
target,
|
|
1356
1383
|
timeout: this.timeout
|
|
1357
1384
|
});
|
|
1385
|
+
|
|
1386
|
+
// IMAP backend returns false for unknown folders
|
|
1387
|
+
return this.assertFolderFound(result);
|
|
1358
1388
|
}
|
|
1359
1389
|
|
|
1360
1390
|
async deleteMessage(message, force) {
|
|
1361
1391
|
await this.loadAccountData(this.account, true);
|
|
1362
1392
|
|
|
1363
|
-
|
|
1393
|
+
let result = await this.call({
|
|
1364
1394
|
cmd: 'deleteMessage',
|
|
1365
1395
|
account: this.account,
|
|
1366
1396
|
message,
|
|
1367
1397
|
force,
|
|
1368
1398
|
timeout: this.timeout
|
|
1369
1399
|
});
|
|
1400
|
+
|
|
1401
|
+
// IMAP backend returns false for unknown messages and folders
|
|
1402
|
+
return this.assertMessageFound(result);
|
|
1370
1403
|
}
|
|
1371
1404
|
|
|
1372
1405
|
async deleteMessages(path, search, force) {
|
|
1373
1406
|
await this.loadAccountData(this.account, true);
|
|
1374
1407
|
|
|
1375
|
-
|
|
1408
|
+
let result = await this.call({
|
|
1376
1409
|
cmd: 'deleteMessages',
|
|
1377
1410
|
account: this.account,
|
|
1378
1411
|
path,
|
|
@@ -1380,6 +1413,9 @@ class Account {
|
|
|
1380
1413
|
force,
|
|
1381
1414
|
timeout: this.timeout
|
|
1382
1415
|
});
|
|
1416
|
+
|
|
1417
|
+
// IMAP backend returns false for unknown folders
|
|
1418
|
+
return this.assertFolderFound(result);
|
|
1383
1419
|
}
|
|
1384
1420
|
|
|
1385
1421
|
async getQuota() {
|
|
@@ -1428,7 +1464,7 @@ class Account {
|
|
|
1428
1464
|
}
|
|
1429
1465
|
|
|
1430
1466
|
async getText(text, options) {
|
|
1431
|
-
if (options.documentStore && (await
|
|
1467
|
+
if (options.documentStore && (await isDocumentStoreEnabled())) {
|
|
1432
1468
|
await this.loadAccountData(this.account, false);
|
|
1433
1469
|
|
|
1434
1470
|
const { index, client } = this.esClient;
|
|
@@ -1447,13 +1483,7 @@ class Account {
|
|
|
1447
1483
|
results: getResult && getResult._source ? 1 : 0
|
|
1448
1484
|
});
|
|
1449
1485
|
|
|
1450
|
-
|
|
1451
|
-
let message = 'Requested message was not found';
|
|
1452
|
-
let error = Boom.boomify(new Error(message), { statusCode: 404 });
|
|
1453
|
-
throw error;
|
|
1454
|
-
}
|
|
1455
|
-
|
|
1456
|
-
let messageData = getResult._source;
|
|
1486
|
+
let messageData = this.assertMessageFound(getResult && getResult._source);
|
|
1457
1487
|
let response = {};
|
|
1458
1488
|
|
|
1459
1489
|
response.hasMore = false;
|
|
@@ -1473,13 +1503,16 @@ class Account {
|
|
|
1473
1503
|
|
|
1474
1504
|
await this.loadAccountData(this.account, true);
|
|
1475
1505
|
|
|
1476
|
-
|
|
1506
|
+
let textData = await this.call({
|
|
1477
1507
|
cmd: 'getText',
|
|
1478
1508
|
account: this.account,
|
|
1479
1509
|
text,
|
|
1480
1510
|
options,
|
|
1481
1511
|
timeout: this.timeout
|
|
1482
1512
|
});
|
|
1513
|
+
|
|
1514
|
+
// IMAP backend returns false for unknown messages and folders
|
|
1515
|
+
return this.assertMessageFound(textData);
|
|
1483
1516
|
}
|
|
1484
1517
|
|
|
1485
1518
|
async getMessage(message, options) {
|
|
@@ -1489,7 +1522,7 @@ class Account {
|
|
|
1489
1522
|
options.preProcessHtml = true;
|
|
1490
1523
|
}
|
|
1491
1524
|
|
|
1492
|
-
if (options.documentStore && (await
|
|
1525
|
+
if (options.documentStore && (await isDocumentStoreEnabled())) {
|
|
1493
1526
|
await this.loadAccountData(this.account, false);
|
|
1494
1527
|
|
|
1495
1528
|
const { index, client } = this.esClient;
|
|
@@ -1521,13 +1554,7 @@ class Account {
|
|
|
1521
1554
|
results: getResult && getResult._source ? 1 : 0
|
|
1522
1555
|
});
|
|
1523
1556
|
|
|
1524
|
-
|
|
1525
|
-
let message = 'Requested message was not found';
|
|
1526
|
-
let error = Boom.boomify(new Error(message), { statusCode: 404 });
|
|
1527
|
-
throw error;
|
|
1528
|
-
}
|
|
1529
|
-
|
|
1530
|
-
let messageData = getResult._source;
|
|
1557
|
+
let messageData = this.assertMessageFound(getResult && getResult._source);
|
|
1531
1558
|
|
|
1532
1559
|
// restore headers and text object as per the API response
|
|
1533
1560
|
let headersObj = {};
|
|
@@ -1632,6 +1659,9 @@ class Account {
|
|
|
1632
1659
|
|
|
1633
1660
|
if (options.markAsSeen && (!messageData.flags || !messageData.flags.includes('\\Seen'))) {
|
|
1634
1661
|
// mark message as seen
|
|
1662
|
+
if (!messageData.flags) {
|
|
1663
|
+
messageData.flags = [];
|
|
1664
|
+
}
|
|
1635
1665
|
messageData.flags.push('\\Seen');
|
|
1636
1666
|
// do not wait until the update is completed, return immediately
|
|
1637
1667
|
this.updateMessage(message, { flags: { add: ['\\Seen'] } }).catch(err => {
|
|
@@ -1661,13 +1691,7 @@ class Account {
|
|
|
1661
1691
|
timeout: this.timeout
|
|
1662
1692
|
});
|
|
1663
1693
|
|
|
1664
|
-
|
|
1665
|
-
let message = 'Requested message was not found';
|
|
1666
|
-
let error = Boom.boomify(new Error(message), { statusCode: 404 });
|
|
1667
|
-
throw error;
|
|
1668
|
-
}
|
|
1669
|
-
|
|
1670
|
-
return messageData;
|
|
1694
|
+
return this.assertMessageFound(messageData);
|
|
1671
1695
|
}
|
|
1672
1696
|
|
|
1673
1697
|
async getMessages(messageIds, options) {
|
|
@@ -1682,7 +1706,7 @@ class Account {
|
|
|
1682
1706
|
}
|
|
1683
1707
|
|
|
1684
1708
|
async listMessages(query) {
|
|
1685
|
-
if (query.documentStore && (await
|
|
1709
|
+
if (query.documentStore && (await isDocumentStoreEnabled())) {
|
|
1686
1710
|
await this.loadAccountData(this.account, false);
|
|
1687
1711
|
|
|
1688
1712
|
const { index, client } = this.esClient;
|
|
@@ -1801,7 +1825,7 @@ class Account {
|
|
|
1801
1825
|
|
|
1802
1826
|
await this.loadAccountData(this.account, true);
|
|
1803
1827
|
|
|
1804
|
-
|
|
1828
|
+
let listing = await this.call(
|
|
1805
1829
|
Object.assign(
|
|
1806
1830
|
{
|
|
1807
1831
|
cmd: 'listMessages',
|
|
@@ -1811,11 +1835,14 @@ class Account {
|
|
|
1811
1835
|
{ timeout: this.timeout }
|
|
1812
1836
|
)
|
|
1813
1837
|
);
|
|
1838
|
+
|
|
1839
|
+
// IMAP and Gmail backends return false for unknown folders
|
|
1840
|
+
return this.assertFolderFound(listing);
|
|
1814
1841
|
}
|
|
1815
1842
|
|
|
1816
1843
|
async searchMessages(query, searchOpts) {
|
|
1817
1844
|
searchOpts = searchOpts || {};
|
|
1818
|
-
if (query.documentStore && (await
|
|
1845
|
+
if (query.documentStore && (await isDocumentStoreEnabled())) {
|
|
1819
1846
|
if (!searchOpts.unified) {
|
|
1820
1847
|
await this.loadAccountData(this.account, false);
|
|
1821
1848
|
}
|
|
@@ -2086,11 +2113,11 @@ class Account {
|
|
|
2086
2113
|
let sizeMatch = {};
|
|
2087
2114
|
|
|
2088
2115
|
if (query.search.larger) {
|
|
2089
|
-
|
|
2116
|
+
sizeMatch.gte = query.search.larger;
|
|
2090
2117
|
}
|
|
2091
2118
|
|
|
2092
2119
|
if (query.search.smaller) {
|
|
2093
|
-
|
|
2120
|
+
sizeMatch.lte = query.search.smaller;
|
|
2094
2121
|
}
|
|
2095
2122
|
|
|
2096
2123
|
if (Object.keys(sizeMatch).length) {
|
|
@@ -2198,7 +2225,7 @@ class Account {
|
|
|
2198
2225
|
|
|
2199
2226
|
await this.loadAccountData(this.account, true);
|
|
2200
2227
|
|
|
2201
|
-
|
|
2228
|
+
let listing = await this.call(
|
|
2202
2229
|
Object.assign(
|
|
2203
2230
|
{
|
|
2204
2231
|
cmd: 'listMessages',
|
|
@@ -2208,6 +2235,9 @@ class Account {
|
|
|
2208
2235
|
{ timeout: this.timeout }
|
|
2209
2236
|
)
|
|
2210
2237
|
);
|
|
2238
|
+
|
|
2239
|
+
// IMAP and Gmail backends return false for unknown folders
|
|
2240
|
+
return this.assertFolderFound(listing);
|
|
2211
2241
|
}
|
|
2212
2242
|
|
|
2213
2243
|
async uploadMessage(data) {
|
|
@@ -2322,7 +2352,7 @@ class Account {
|
|
|
2322
2352
|
}
|
|
2323
2353
|
} catch (err) {
|
|
2324
2354
|
this.logger.error({ msg: 'Failed to get lock', lockKey, err });
|
|
2325
|
-
if (Boom.isBoom) {
|
|
2355
|
+
if (Boom.isBoom(err)) {
|
|
2326
2356
|
throw err;
|
|
2327
2357
|
}
|
|
2328
2358
|
let error = Boom.boomify(new Error('Failed to get flush lock, try again later'), { statusCode: 500 });
|
|
@@ -2377,11 +2407,13 @@ class Account {
|
|
|
2377
2407
|
// scan and delete keys
|
|
2378
2408
|
await redisScanDelete(this.redis, this.logger, `${REDIS_PREFIX}iam:${this.account}:*`);
|
|
2379
2409
|
|
|
2380
|
-
if (await
|
|
2410
|
+
if (await isDocumentStoreEnabled()) {
|
|
2381
2411
|
// Flush ElasticSearch index for this account
|
|
2382
2412
|
const { index, client } = this.esClient;
|
|
2383
2413
|
if (!client) {
|
|
2384
|
-
|
|
2414
|
+
// Account data in Redis was already flushed, only the index cleanup was skipped
|
|
2415
|
+
this.logger.error({ msg: 'Document store is enabled but the ElasticSearch client is not available', action: 'flush' });
|
|
2416
|
+
return true;
|
|
2385
2417
|
}
|
|
2386
2418
|
|
|
2387
2419
|
let deleteResult = {};
|
|
@@ -2592,7 +2624,7 @@ class Account {
|
|
|
2592
2624
|
account: accountData.account,
|
|
2593
2625
|
user: authData.user,
|
|
2594
2626
|
accessToken: authData.accessToken,
|
|
2595
|
-
provider: accountData.oauth2.
|
|
2627
|
+
provider: accountData.oauth2.provider,
|
|
2596
2628
|
registeredScopes: accountData.oauth2.scope,
|
|
2597
2629
|
cached: false
|
|
2598
2630
|
};
|
|
@@ -2626,7 +2658,7 @@ class Account {
|
|
|
2626
2658
|
account: accountData.account,
|
|
2627
2659
|
user: accountData.oauth2.auth.user,
|
|
2628
2660
|
accessToken,
|
|
2629
|
-
provider: accountData.oauth2.
|
|
2661
|
+
provider: accountData.oauth2.provider,
|
|
2630
2662
|
registeredScopes: accountData.oauth2.scope,
|
|
2631
2663
|
expires:
|
|
2632
2664
|
accountData.oauth2.expires && typeof accountData.oauth2.expires.toISOString === 'function'
|