@sockethub/platform-carddav 1.0.0-beta.1 → 1.0.0-beta.3
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 +13 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +152 -41
- package/dist/index.js.map +7 -7
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -12,6 +12,19 @@ including IPv6 embeddings of private ranges and the local-use NAT64 prefix
|
|
|
12
12
|
Authentication supports Basic, Digest, or a caller-provided Bearer token
|
|
13
13
|
through the standard Sockethub credentials flow.
|
|
14
14
|
|
|
15
|
+
## Discovery cache
|
|
16
|
+
|
|
17
|
+
Each `query`, `create`, `update`, and `delete` needs the account's address book list to
|
|
18
|
+
check the target. The platform caches that discovery result in memory for
|
|
19
|
+
`packageConfig.discoveryCacheTtlMs` (default `300000`, 5 minutes; `0`
|
|
20
|
+
disables the cache). Entries are keyed by an HMAC of the protocol, service URL,
|
|
21
|
+
and credentials. The HMAC uses a per-process random secret, and only
|
|
22
|
+
collection metadata is stored. A `fetch` always discovers fresh. Within the TTL,
|
|
23
|
+
an address book added on the server is not visible to targeted actions, and a removed
|
|
24
|
+
one is still accepted as a target (the server then rejects the request). An
|
|
25
|
+
authentication, not-found, or unknown-address-book error drops the entry, so the next
|
|
26
|
+
request rediscovers. The cache is lost when the platform process restarts.
|
|
27
|
+
|
|
15
28
|
## Authentication
|
|
16
29
|
|
|
17
30
|
Send credentials before performing CardDAV actions. Use either a username and
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,10 @@ import type { ActivityStream, PlatformCallback, PlatformInterface, PlatformSchem
|
|
|
2
2
|
import type { CardDavCredentials } from "./types.js";
|
|
3
3
|
export default class CardDav implements PlatformInterface {
|
|
4
4
|
private readonly log;
|
|
5
|
-
|
|
5
|
+
private readonly discovery;
|
|
6
|
+
config: StatelessPlatformConfig & {
|
|
7
|
+
discoveryCacheTtlMs: number;
|
|
8
|
+
};
|
|
6
9
|
constructor(session: PlatformSession);
|
|
7
10
|
get schema(): PlatformSchemaStruct;
|
|
8
11
|
isInitialized(): boolean;
|
|
@@ -13,6 +16,7 @@ export default class CardDav implements PlatformInterface {
|
|
|
13
16
|
update(job: ActivityStream, credentials: CardDavCredentials, done: PlatformCallback): void;
|
|
14
17
|
delete(job: ActivityStream, credentials: CardDavCredentials, done: PlatformCallback): void;
|
|
15
18
|
private client;
|
|
19
|
+
private discoveryKey;
|
|
16
20
|
private book;
|
|
17
21
|
private mutation;
|
|
18
22
|
private fail;
|
package/dist/index.js
CHANGED
|
@@ -15762,7 +15762,7 @@ var require_ajv_formats_draft2019 = __commonJS(function(exports, module) {
|
|
|
15762
15762
|
|
|
15763
15763
|
// ../dav/dist/index.js
|
|
15764
15764
|
import { createRequire as createRequire2 } from "node:module";
|
|
15765
|
-
import { createHash, randomBytes } from "node:crypto";
|
|
15765
|
+
import { createHash, createHmac, randomBytes } from "node:crypto";
|
|
15766
15766
|
import { lookup as dnsLookup } from "node:dns";
|
|
15767
15767
|
import { isIP } from "node:net";
|
|
15768
15768
|
var __commonJS2 = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
@@ -39185,7 +39185,7 @@ function createGuardedLookup(allowPrivateAddresses) {
|
|
|
39185
39185
|
if (!allowPrivateAddresses) {
|
|
39186
39186
|
for (const { address } of addresses) {
|
|
39187
39187
|
if (isBlockedAddress(address)) {
|
|
39188
|
-
callback(new Error(`blocked non-public address
|
|
39188
|
+
callback(new Error(`blocked non-public address for ${hostname}`));
|
|
39189
39189
|
return;
|
|
39190
39190
|
}
|
|
39191
39191
|
}
|
|
@@ -42746,6 +42746,82 @@ function isDavCollectionChild(collectionId, resourceId) {
|
|
|
42746
42746
|
return false;
|
|
42747
42747
|
}
|
|
42748
42748
|
}
|
|
42749
|
+
|
|
42750
|
+
class DiscoveryCache {
|
|
42751
|
+
maxEntries;
|
|
42752
|
+
secret = randomBytes(32);
|
|
42753
|
+
entries = new Map;
|
|
42754
|
+
pending = new Map;
|
|
42755
|
+
timer;
|
|
42756
|
+
timerAt = Number.POSITIVE_INFINITY;
|
|
42757
|
+
constructor(maxEntries = 1000) {
|
|
42758
|
+
this.maxEntries = maxEntries;
|
|
42759
|
+
}
|
|
42760
|
+
key(...identity) {
|
|
42761
|
+
return createHmac("sha256", this.secret).update(JSON.stringify(identity)).digest("hex");
|
|
42762
|
+
}
|
|
42763
|
+
async get(key, ttlMs, discover) {
|
|
42764
|
+
if (!(ttlMs > 0))
|
|
42765
|
+
return discover();
|
|
42766
|
+
const hit = this.entries.get(key);
|
|
42767
|
+
if (hit && hit.expires > Date.now())
|
|
42768
|
+
return hit.value;
|
|
42769
|
+
const inFlight = this.pending.get(key);
|
|
42770
|
+
if (inFlight)
|
|
42771
|
+
return inFlight;
|
|
42772
|
+
const promise = discover();
|
|
42773
|
+
this.pending.set(key, promise);
|
|
42774
|
+
try {
|
|
42775
|
+
const value = await promise;
|
|
42776
|
+
if (this.pending.get(key) === promise)
|
|
42777
|
+
this.store(key, value, Date.now() + ttlMs);
|
|
42778
|
+
return value;
|
|
42779
|
+
} finally {
|
|
42780
|
+
if (this.pending.get(key) === promise)
|
|
42781
|
+
this.pending.delete(key);
|
|
42782
|
+
}
|
|
42783
|
+
}
|
|
42784
|
+
delete(key) {
|
|
42785
|
+
this.entries.delete(key);
|
|
42786
|
+
this.pending.delete(key);
|
|
42787
|
+
}
|
|
42788
|
+
get size() {
|
|
42789
|
+
return this.entries.size;
|
|
42790
|
+
}
|
|
42791
|
+
store(key, value, expires) {
|
|
42792
|
+
this.entries.delete(key);
|
|
42793
|
+
if (this.entries.size >= this.maxEntries) {
|
|
42794
|
+
this.sweep();
|
|
42795
|
+
if (this.entries.size >= this.maxEntries)
|
|
42796
|
+
this.entries.delete(this.entries.keys().next().value);
|
|
42797
|
+
}
|
|
42798
|
+
this.entries.set(key, { expires, value });
|
|
42799
|
+
this.schedule(expires);
|
|
42800
|
+
}
|
|
42801
|
+
sweep() {
|
|
42802
|
+
const now = Date.now();
|
|
42803
|
+
for (const [key, entry] of this.entries)
|
|
42804
|
+
if (entry.expires <= now)
|
|
42805
|
+
this.entries.delete(key);
|
|
42806
|
+
}
|
|
42807
|
+
schedule(at) {
|
|
42808
|
+
if (this.timer && at >= this.timerAt)
|
|
42809
|
+
return;
|
|
42810
|
+
clearTimeout(this.timer);
|
|
42811
|
+
this.timerAt = at;
|
|
42812
|
+
this.timer = setTimeout(() => {
|
|
42813
|
+
this.timer = undefined;
|
|
42814
|
+
this.timerAt = Number.POSITIVE_INFINITY;
|
|
42815
|
+
this.sweep();
|
|
42816
|
+
let next = Number.POSITIVE_INFINITY;
|
|
42817
|
+
for (const entry of this.entries.values())
|
|
42818
|
+
next = Math.min(next, entry.expires);
|
|
42819
|
+
if (next !== Number.POSITIVE_INFINITY)
|
|
42820
|
+
this.schedule(next);
|
|
42821
|
+
}, Math.min(Math.max(0, at - Date.now()), 2147483647));
|
|
42822
|
+
this.timer.unref?.();
|
|
42823
|
+
}
|
|
42824
|
+
}
|
|
42749
42825
|
function unquote(value) {
|
|
42750
42826
|
return value.startsWith('"') ? value.slice(1, -1).replace(/\\(.)/g, "$1") : value;
|
|
42751
42827
|
}
|
|
@@ -43199,7 +43275,7 @@ var ActivityStreamSchema = {
|
|
|
43199
43275
|
var package_default = {
|
|
43200
43276
|
name: "@sockethub/schemas",
|
|
43201
43277
|
description: "JSON schema files for validating Sockethub Activity Streams",
|
|
43202
|
-
version: "3.0.0-beta.
|
|
43278
|
+
version: "3.0.0-beta.3",
|
|
43203
43279
|
type: "module",
|
|
43204
43280
|
private: false,
|
|
43205
43281
|
author: "Nick Jennings <nick@silverbucket.net>",
|
|
@@ -43269,7 +43345,7 @@ var package_default = {
|
|
|
43269
43345
|
"ajv-formats": "^2.1.1",
|
|
43270
43346
|
"ajv-formats-draft2019": "^1.6.1"
|
|
43271
43347
|
},
|
|
43272
|
-
gitHead: "
|
|
43348
|
+
gitHead: "bc04522d60d1e2fa1b3098b339897de62c3b0549",
|
|
43273
43349
|
types: "./dist/index.d.ts"
|
|
43274
43350
|
};
|
|
43275
43351
|
|
|
@@ -43374,8 +43450,12 @@ var SockethubConfigSchema = {
|
|
|
43374
43450
|
"@sockethub/platform-caldav",
|
|
43375
43451
|
"@sockethub/platform-dummy",
|
|
43376
43452
|
"@sockethub/platform-feeds",
|
|
43453
|
+
"@sockethub/platform-email",
|
|
43377
43454
|
"@sockethub/platform-irc",
|
|
43378
43455
|
"@sockethub/platform-metadata",
|
|
43456
|
+
"@sockethub/platform-messenger",
|
|
43457
|
+
"@sockethub/platform-instagram",
|
|
43458
|
+
"@sockethub/platform-whatsapp",
|
|
43379
43459
|
"@sockethub/platform-xmpp"
|
|
43380
43460
|
]
|
|
43381
43461
|
},
|
|
@@ -43391,7 +43471,8 @@ var SockethubConfigSchema = {
|
|
|
43391
43471
|
connectTimeoutMs: { type: "integer", minimum: 1 },
|
|
43392
43472
|
allowPrivateAddresses: { type: "boolean" },
|
|
43393
43473
|
allowInsecureHttp: { type: "boolean" },
|
|
43394
|
-
concurrency: { type: "integer", minimum: 1 }
|
|
43474
|
+
concurrency: { type: "integer", minimum: 1 },
|
|
43475
|
+
discoveryCacheTtlMs: { type: "integer", minimum: 0 }
|
|
43395
43476
|
}
|
|
43396
43477
|
},
|
|
43397
43478
|
"@sockethub/platform-caldav": {
|
|
@@ -43401,7 +43482,20 @@ var SockethubConfigSchema = {
|
|
|
43401
43482
|
connectTimeoutMs: { type: "integer", minimum: 1 },
|
|
43402
43483
|
allowPrivateAddresses: { type: "boolean" },
|
|
43403
43484
|
allowInsecureHttp: { type: "boolean" },
|
|
43404
|
-
concurrency: { type: "integer", minimum: 1 }
|
|
43485
|
+
concurrency: { type: "integer", minimum: 1 },
|
|
43486
|
+
discoveryCacheTtlMs: { type: "integer", minimum: 0 }
|
|
43487
|
+
}
|
|
43488
|
+
},
|
|
43489
|
+
"@sockethub/platform-email": {
|
|
43490
|
+
type: "object",
|
|
43491
|
+
additionalProperties: false,
|
|
43492
|
+
properties: {
|
|
43493
|
+
connectTimeoutMs: {
|
|
43494
|
+
type: "integer",
|
|
43495
|
+
minimum: 5000,
|
|
43496
|
+
maximum: 120000
|
|
43497
|
+
},
|
|
43498
|
+
allowPrivateAddresses: { type: "boolean" }
|
|
43405
43499
|
}
|
|
43406
43500
|
},
|
|
43407
43501
|
"@sockethub/platform-dummy": {
|
|
@@ -43424,7 +43518,8 @@ var SockethubConfigSchema = {
|
|
|
43424
43518
|
type: "object",
|
|
43425
43519
|
additionalProperties: false,
|
|
43426
43520
|
properties: {
|
|
43427
|
-
connectTimeoutMs: { type: "number" }
|
|
43521
|
+
connectTimeoutMs: { type: "number" },
|
|
43522
|
+
allowPrivateAddresses: { type: "boolean" }
|
|
43428
43523
|
}
|
|
43429
43524
|
},
|
|
43430
43525
|
"@sockethub/platform-xmpp": {
|
|
@@ -43534,6 +43629,12 @@ var SockethubConfigSchema = {
|
|
|
43534
43629
|
default: 20,
|
|
43535
43630
|
description: "Maximum persistent instances per client IP, including HTTP actions. 0 disables the cap."
|
|
43536
43631
|
},
|
|
43632
|
+
maxStartsPerIpPerMinute: {
|
|
43633
|
+
type: "integer",
|
|
43634
|
+
minimum: 0,
|
|
43635
|
+
default: 60,
|
|
43636
|
+
description: "Maximum new persistent instances a client IP may start per minute, " + "including HTTP actions. Bounds fork/teardown churn that the " + "concurrent caps allow. Reusing a running instance does not count. " + "0 disables the cap."
|
|
43637
|
+
},
|
|
43537
43638
|
maxPlatformInstances: {
|
|
43538
43639
|
type: "number",
|
|
43539
43640
|
minimum: 0,
|
|
@@ -43842,8 +43943,10 @@ function splitEscaped(value, separator) {
|
|
|
43842
43943
|
result.push(current);
|
|
43843
43944
|
return result;
|
|
43844
43945
|
}
|
|
43845
|
-
|
|
43846
|
-
|
|
43946
|
+
function unescapeText(value) {
|
|
43947
|
+
return value.replaceAll(/\\([nN,;\\])/g, (_match, character) => character === "n" || character === "N" ? `
|
|
43948
|
+
` : character);
|
|
43949
|
+
}
|
|
43847
43950
|
var escapeText = (value) => value.replace(/\r\n?/g, `
|
|
43848
43951
|
`).replaceAll("\\", "\\\\").replaceAll(`
|
|
43849
43952
|
`, "\\n").replaceAll(";", "\\;").replaceAll(",", "\\,");
|
|
@@ -44079,20 +44182,20 @@ function params(value) {
|
|
|
44079
44182
|
}
|
|
44080
44183
|
function fold(line) {
|
|
44081
44184
|
const chunks = [];
|
|
44082
|
-
let
|
|
44083
|
-
|
|
44084
|
-
|
|
44085
|
-
|
|
44086
|
-
|
|
44087
|
-
|
|
44088
|
-
|
|
44089
|
-
|
|
44090
|
-
|
|
44091
|
-
|
|
44092
|
-
|
|
44093
|
-
|
|
44094
|
-
}
|
|
44095
|
-
chunks.push(
|
|
44185
|
+
let start = 0;
|
|
44186
|
+
let end = 0;
|
|
44187
|
+
let octets = 0;
|
|
44188
|
+
for (const char of line) {
|
|
44189
|
+
const size = Buffer.byteLength(char, "utf8");
|
|
44190
|
+
if (octets + size > (chunks.length ? 74 : 75)) {
|
|
44191
|
+
chunks.push(line.slice(start, end));
|
|
44192
|
+
start = end;
|
|
44193
|
+
octets = 0;
|
|
44194
|
+
}
|
|
44195
|
+
octets += size;
|
|
44196
|
+
end += char.length;
|
|
44197
|
+
}
|
|
44198
|
+
chunks.push(line.slice(start));
|
|
44096
44199
|
return chunks.join(`\r
|
|
44097
44200
|
`);
|
|
44098
44201
|
}
|
|
@@ -44383,7 +44486,7 @@ class CardDavClient extends DavClient {
|
|
|
44383
44486
|
var package_default2 = {
|
|
44384
44487
|
name: "@sockethub/platform-carddav",
|
|
44385
44488
|
description: "A Sockethub platform for CardDAV address books and contacts",
|
|
44386
|
-
version: "1.0.0-beta.
|
|
44489
|
+
version: "1.0.0-beta.3",
|
|
44387
44490
|
type: "module",
|
|
44388
44491
|
private: false,
|
|
44389
44492
|
license: "LGPL-3.0+",
|
|
@@ -44412,21 +44515,21 @@ var package_default2 = {
|
|
|
44412
44515
|
test: "bun test src/"
|
|
44413
44516
|
},
|
|
44414
44517
|
dependencies: {
|
|
44415
|
-
"@sockethub/dav": "^1.0.0-beta.
|
|
44416
|
-
"@sockethub/schemas": "^3.0.0-beta.
|
|
44518
|
+
"@sockethub/dav": "^1.0.0-beta.3",
|
|
44519
|
+
"@sockethub/schemas": "^3.0.0-beta.3"
|
|
44417
44520
|
},
|
|
44418
44521
|
devDependencies: {
|
|
44419
44522
|
"@types/bun": "latest"
|
|
44420
44523
|
},
|
|
44421
44524
|
peerDependencies: {
|
|
44422
|
-
"@sockethub/server": "^5.0.0-beta.
|
|
44525
|
+
"@sockethub/server": "^5.0.0-beta.3"
|
|
44423
44526
|
},
|
|
44424
44527
|
peerDependenciesMeta: {
|
|
44425
44528
|
"@sockethub/server": {
|
|
44426
44529
|
optional: true
|
|
44427
44530
|
}
|
|
44428
44531
|
},
|
|
44429
|
-
gitHead: "
|
|
44532
|
+
gitHead: "bc04522d60d1e2fa1b3098b339897de62c3b0549"
|
|
44430
44533
|
};
|
|
44431
44534
|
|
|
44432
44535
|
// src/schema.ts
|
|
@@ -44719,13 +44822,15 @@ var CONTEXT = buildCanonicalContext(PlatformCardDavSchema.contextUrl);
|
|
|
44719
44822
|
|
|
44720
44823
|
class CardDav {
|
|
44721
44824
|
log;
|
|
44825
|
+
discovery = new DiscoveryCache;
|
|
44722
44826
|
config = {
|
|
44723
44827
|
persist: false,
|
|
44724
44828
|
requireCredentials: ["fetch", "query", "create", "update", "delete"],
|
|
44725
44829
|
connectTimeoutMs: 15000,
|
|
44726
44830
|
allowPrivateAddresses: false,
|
|
44727
44831
|
allowInsecureHttp: false,
|
|
44728
|
-
concurrency: 10
|
|
44832
|
+
concurrency: 10,
|
|
44833
|
+
discoveryCacheTtlMs: 300000
|
|
44729
44834
|
};
|
|
44730
44835
|
constructor(session) {
|
|
44731
44836
|
this.log = session.log;
|
|
@@ -44748,40 +44853,40 @@ class CardDav {
|
|
|
44748
44853
|
summary: "CardDAV address books",
|
|
44749
44854
|
totalItems: items.length,
|
|
44750
44855
|
items
|
|
44751
|
-
})).catch((error) => this.fail(job, error, done)).finally(() => client.close().catch(() => {}));
|
|
44856
|
+
})).catch((error) => this.fail(job, error, done, credentials)).finally(() => client.close().catch(() => {}));
|
|
44752
44857
|
}
|
|
44753
44858
|
query(job, credentials, done) {
|
|
44754
44859
|
const client = this.client(credentials);
|
|
44755
|
-
this.book(client, job.target?.id ?? "").then((book) => client.query(book, job.object ?? {})).then((items) => done(null, {
|
|
44860
|
+
this.book(client, credentials, job.target?.id ?? "").then((book) => client.query(book, job.object ?? {})).then((items) => done(null, {
|
|
44756
44861
|
"@context": CONTEXT,
|
|
44757
44862
|
...job.id ? { id: job.id } : {},
|
|
44758
44863
|
type: "collection",
|
|
44759
44864
|
summary: "CardDAV contacts",
|
|
44760
44865
|
totalItems: items.length,
|
|
44761
44866
|
items
|
|
44762
|
-
})).catch((error) => this.fail(job, error, done)).finally(() => client.close().catch(() => {}));
|
|
44867
|
+
})).catch((error) => this.fail(job, error, done, credentials)).finally(() => client.close().catch(() => {}));
|
|
44763
44868
|
}
|
|
44764
44869
|
create(job, credentials, done) {
|
|
44765
44870
|
const client = this.client(credentials);
|
|
44766
|
-
this.book(client, job.target?.id ?? "").then((book) => client.create(book, job.object)).then((result) => done(null, this.mutation(job, "create", result))).catch((error) => this.fail(job, error, done)).finally(() => client.close().catch(() => {}));
|
|
44871
|
+
this.book(client, credentials, job.target?.id ?? "").then((book) => client.create(book, job.object)).then((result) => done(null, this.mutation(job, "create", result))).catch((error) => this.fail(job, error, done, credentials)).finally(() => client.close().catch(() => {}));
|
|
44767
44872
|
}
|
|
44768
44873
|
update(job, credentials, done) {
|
|
44769
44874
|
const client = this.client(credentials);
|
|
44770
44875
|
const input = job.object;
|
|
44771
|
-
this.book(client, job.target?.id ?? "").then((book) => {
|
|
44876
|
+
this.book(client, credentials, job.target?.id ?? "").then((book) => {
|
|
44772
44877
|
if (!isDavCollectionChild(book.id, input.id))
|
|
44773
44878
|
throw new DavFailure("carddav:invalid-resource");
|
|
44774
44879
|
return client.update(input);
|
|
44775
|
-
}).then((result) => done(null, this.mutation(job, "update", result))).catch((error) => this.fail(job, error, done)).finally(() => client.close().catch(() => {}));
|
|
44880
|
+
}).then((result) => done(null, this.mutation(job, "update", result))).catch((error) => this.fail(job, error, done, credentials)).finally(() => client.close().catch(() => {}));
|
|
44776
44881
|
}
|
|
44777
44882
|
delete(job, credentials, done) {
|
|
44778
44883
|
const client = this.client(credentials);
|
|
44779
44884
|
const input = job.object;
|
|
44780
|
-
this.book(client, job.target?.id ?? "").then((book) => {
|
|
44885
|
+
this.book(client, credentials, job.target?.id ?? "").then((book) => {
|
|
44781
44886
|
if (!isDavCollectionChild(book.id, input.id))
|
|
44782
44887
|
throw new DavFailure("carddav:invalid-resource");
|
|
44783
44888
|
return client.delete(input.id, input.etag);
|
|
44784
|
-
}).then(() => done(null, this.mutation(job, "delete", { id: input.id }))).catch((error) => this.fail(job, error, done)).finally(() => client.close().catch(() => {}));
|
|
44889
|
+
}).then(() => done(null, this.mutation(job, "delete", { id: input.id }))).catch((error) => this.fail(job, error, done, credentials)).finally(() => client.close().catch(() => {}));
|
|
44785
44890
|
}
|
|
44786
44891
|
client(credentials) {
|
|
44787
44892
|
const { url, ...authentication } = credentials.object;
|
|
@@ -44790,14 +44895,18 @@ class CardDav {
|
|
|
44790
44895
|
allowInsecureHttp: this.config.allowInsecureHttp
|
|
44791
44896
|
});
|
|
44792
44897
|
}
|
|
44793
|
-
|
|
44898
|
+
discoveryKey(credentials) {
|
|
44899
|
+
return this.discovery.key("carddav", credentials.object);
|
|
44900
|
+
}
|
|
44901
|
+
async book(client, credentials, id) {
|
|
44794
44902
|
let normalized;
|
|
44795
44903
|
try {
|
|
44796
44904
|
normalized = new URL(id).href;
|
|
44797
44905
|
} catch {
|
|
44798
44906
|
throw new DavFailure("carddav:invalid-address-book");
|
|
44799
44907
|
}
|
|
44800
|
-
const
|
|
44908
|
+
const books = await this.discovery.get(this.discoveryKey(credentials), this.config.discoveryCacheTtlMs, () => client.discoverAddressBooks());
|
|
44909
|
+
const book = books.find((item) => item.id === normalized);
|
|
44801
44910
|
if (!book)
|
|
44802
44911
|
throw new DavFailure("carddav:invalid-address-book");
|
|
44803
44912
|
return book;
|
|
@@ -44817,7 +44926,9 @@ class CardDav {
|
|
|
44817
44926
|
}
|
|
44818
44927
|
};
|
|
44819
44928
|
}
|
|
44820
|
-
fail(job, error, done) {
|
|
44929
|
+
fail(job, error, done, credentials) {
|
|
44930
|
+
if (credentials && error instanceof DavFailure && /:(authentication-failed|not-found|invalid-address-book)$/.test(error.code))
|
|
44931
|
+
this.discovery.delete(this.discoveryKey(credentials));
|
|
44821
44932
|
const code = error instanceof DavFailure ? error.code : `carddav:invalid-${job.type}`;
|
|
44822
44933
|
this.log.error(`CardDAV ${job.type} failed for actor ${job.actor.id}`, {
|
|
44823
44934
|
code,
|
|
@@ -44835,4 +44946,4 @@ export {
|
|
|
44835
44946
|
parseVCard
|
|
44836
44947
|
};
|
|
44837
44948
|
|
|
44838
|
-
//# debugId=
|
|
44949
|
+
//# debugId=D20292E281EC330764756E2164756E21
|