core-3nweb-client-lib 0.38.0 → 0.39.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/build/api-defs/asmail.d.ts +0 -16
- package/build/api-defs/keys.d.ts +3 -0
- package/build/api-defs/web3n.d.ts +33 -7
- package/build/core/asmail/inbox/index.js +1 -1
- package/build/core/asmail/sending-params/invitations-anon.js +1 -1
- package/build/core/id-manager/index.js +2 -10
- package/build/core/index.js +2 -0
- package/build/core/keyring/correspondent-keys.d.ts +18 -19
- package/build/core/keyring/correspondent-keys.js +4 -1
- package/build/lib-client/server-events.js +1 -1
- package/build/lib-client/service-locator.js +15 -16
- package/build/lib-common/exceptions/http.d.ts +3 -3
- package/build/lib-common/exceptions/http.js +6 -26
- package/package.json +1 -1
|
@@ -301,22 +301,6 @@ declare namespace web3n.asmail {
|
|
|
301
301
|
msgIsBroken?: true;
|
|
302
302
|
}
|
|
303
303
|
|
|
304
|
-
interface ServLocException extends RuntimeException {
|
|
305
|
-
type: 'service-locating';
|
|
306
|
-
address: string;
|
|
307
|
-
|
|
308
|
-
/**
|
|
309
|
-
* domainNotFound flag indicates that domain in the address doesn't exist.
|
|
310
|
-
*/
|
|
311
|
-
domainNotFound?: true;
|
|
312
|
-
|
|
313
|
-
/**
|
|
314
|
-
* noServiceRecord flag indicates that 3NWeb services are not set at
|
|
315
|
-
* domain in the address.
|
|
316
|
-
*/
|
|
317
|
-
noServiceRecord?: true;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
304
|
interface ASMailSendException extends RuntimeException {
|
|
321
305
|
type: 'asmail-delivery';
|
|
322
306
|
address?: string;
|
package/build/api-defs/keys.d.ts
CHANGED
|
@@ -167,12 +167,14 @@ declare namespace web3n.keys {
|
|
|
167
167
|
interface IntroductorySendingPairInfo {
|
|
168
168
|
type: 'intro';
|
|
169
169
|
recipientKId: string;
|
|
170
|
+
alg: string;
|
|
170
171
|
}
|
|
171
172
|
|
|
172
173
|
interface RatchetedSendingPairInfo {
|
|
173
174
|
type: 'ratcheted';
|
|
174
175
|
pids: string[];
|
|
175
176
|
timestamp: number;
|
|
177
|
+
alg: string;
|
|
176
178
|
senderKId: string;
|
|
177
179
|
recipientKId: string;
|
|
178
180
|
sentMsgs?: {
|
|
@@ -183,6 +185,7 @@ declare namespace web3n.keys {
|
|
|
183
185
|
|
|
184
186
|
interface ReceptionPairInfo {
|
|
185
187
|
pids: string[];
|
|
188
|
+
alg: string;
|
|
186
189
|
recipientKId: string;
|
|
187
190
|
isSenderIntroKey?: boolean,
|
|
188
191
|
senderKId: string;
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
declare namespace web3n {
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
interface RuntimeException {
|
|
30
30
|
runtimeException: true;
|
|
31
31
|
type?: string;
|
|
@@ -33,21 +33,47 @@ declare namespace web3n {
|
|
|
33
33
|
message?: string;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
interface ConnectException extends RuntimeException {
|
|
37
|
+
type: 'connect';
|
|
38
|
+
connectType: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
36
41
|
interface HTTPErrorDetails extends web3n.RuntimeException {
|
|
37
42
|
url: string;
|
|
38
43
|
method: string;
|
|
39
|
-
message?: string;
|
|
40
44
|
}
|
|
41
|
-
|
|
42
|
-
interface
|
|
43
|
-
|
|
45
|
+
|
|
46
|
+
interface HTTPConnectException extends ConnectException {
|
|
47
|
+
connectType: 'http';
|
|
48
|
+
url?: string;
|
|
49
|
+
method?: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
interface DNSConnectException extends ConnectException {
|
|
53
|
+
connectType: 'dns';
|
|
44
54
|
}
|
|
45
|
-
|
|
55
|
+
|
|
46
56
|
interface HTTPException extends HTTPErrorDetails {
|
|
47
57
|
type: 'http-request';
|
|
48
58
|
status: number;
|
|
49
59
|
}
|
|
50
|
-
|
|
60
|
+
|
|
61
|
+
interface ServLocException extends RuntimeException {
|
|
62
|
+
type: 'service-locating';
|
|
63
|
+
address: string;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* domainNotFound flag indicates that domain in the address doesn't exist.
|
|
67
|
+
*/
|
|
68
|
+
domainNotFound?: true;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* noServiceRecord flag indicates that 3NWeb services are not set at
|
|
72
|
+
* domain in the address.
|
|
73
|
+
*/
|
|
74
|
+
noServiceRecord?: true;
|
|
75
|
+
}
|
|
76
|
+
|
|
51
77
|
interface EncryptionException {
|
|
52
78
|
failedCipherVerification?: true;
|
|
53
79
|
failedSignatureVerification?: true;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2015 - 2018, 2020 - 2022 3NSoft Inc.
|
|
3
|
+
Copyright (C) 2015 - 2018, 2020 - 2022, 2025 3NSoft Inc.
|
|
4
4
|
|
|
5
5
|
This program is free software: you can redistribute it and/or modify it under
|
|
6
6
|
the terms of the GNU General Public License as published by the Free Software
|
|
@@ -72,15 +72,7 @@ class IdManager {
|
|
|
72
72
|
}
|
|
73
73
|
static async initFromCachedStore(address, fs, resolver, makeNet, logError, logWarning) {
|
|
74
74
|
const store = key_storage_1.IdKeysStorage.makeWithStorage(fs, logError, logWarning);
|
|
75
|
-
|
|
76
|
-
try {
|
|
77
|
-
await idManager.provisionUsingSavedKey();
|
|
78
|
-
return idManager;
|
|
79
|
-
}
|
|
80
|
-
catch (err) {
|
|
81
|
-
await logError(err, `Can't initialize id manager from local store`);
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
75
|
+
return new IdManager(store, makeNet, resolver, address);
|
|
84
76
|
}
|
|
85
77
|
async startProvisionWithoutSavedKey(address) {
|
|
86
78
|
const midUrl = await this.midServiceFor(address);
|
package/build/core/index.js
CHANGED
|
@@ -86,6 +86,7 @@ class Core {
|
|
|
86
86
|
};
|
|
87
87
|
};
|
|
88
88
|
this.initForExistingUserWithCache = async (address, storageKey) => {
|
|
89
|
+
// XXX this shouldn't fail without network. All data is on the disk!
|
|
89
90
|
const completeStorageInit = await this.storages.startInitFromCache(address, storageKey, this.makeNet, this.makeResolver('3nstorage'), this.logger.logError);
|
|
90
91
|
if (!completeStorageInit) {
|
|
91
92
|
return;
|
|
@@ -222,6 +223,7 @@ class Core {
|
|
|
222
223
|
// XXX This should be removed, at some point, as there will be no more
|
|
223
224
|
// users with very old data folders.
|
|
224
225
|
await this.performDataMigrationsAtInit();
|
|
226
|
+
// XXX some of these starting can be done any way
|
|
225
227
|
const keyringsSyncedFS = await this.storages.makeSyncedFSForApp(constants_1.KEYRINGS_APP_NAME);
|
|
226
228
|
await this.keyrings.init(keyringsSyncedFS, this.idManager.getSigner, asmailServerConfig.makeParamSetterAndGetter('init-pub-key'));
|
|
227
229
|
const inboxSyncedFS = await this.storages.makeSyncedFSForApp(constants_1.ASMAIL_APP_NAME);
|
|
@@ -21,23 +21,6 @@ export interface ReceptionPair {
|
|
|
21
21
|
};
|
|
22
22
|
timestamp: number;
|
|
23
23
|
}
|
|
24
|
-
/**
|
|
25
|
-
* Sending pairs are a rotating public key cryptography key material for sending
|
|
26
|
-
* messages.
|
|
27
|
-
*
|
|
28
|
-
* Let's note naming convention. Since this is a sending pair, this side of
|
|
29
|
-
* communication is called a sender, while the other side is a recipient.
|
|
30
|
-
*/
|
|
31
|
-
export interface BaseSendingPair {
|
|
32
|
-
/**
|
|
33
|
-
* This is recipients' public key, to which encryption is done.
|
|
34
|
-
* If this is an introductory pair, this key is recipient's published intro
|
|
35
|
-
* public key.
|
|
36
|
-
* Else, if this is an ratcheted pair, this key comes from crypto material
|
|
37
|
-
* that recipients suggests from time to time for further use.
|
|
38
|
-
*/
|
|
39
|
-
recipientPKey: JsonKeyShort;
|
|
40
|
-
}
|
|
41
24
|
/**
|
|
42
25
|
* Introductory pair appears when the first message is sent to a new
|
|
43
26
|
* correspondent. By nature it is an introductory message that uses recipient's
|
|
@@ -48,14 +31,22 @@ export interface BaseSendingPair {
|
|
|
48
31
|
* a flag that allows to distinguish it from ratcheted pair with a clean
|
|
49
32
|
* if-statement.
|
|
50
33
|
*/
|
|
51
|
-
export interface IntroductorySendingPair
|
|
34
|
+
export interface IntroductorySendingPair {
|
|
52
35
|
type: 'intro';
|
|
36
|
+
/**
|
|
37
|
+
* This is recipients' public key, to which encryption is done.
|
|
38
|
+
* If this is an introductory pair, this key is recipient's published intro
|
|
39
|
+
* public key.
|
|
40
|
+
* Else, if this is an ratcheted pair, this key comes from crypto material
|
|
41
|
+
* that recipients suggests from time to time for further use.
|
|
42
|
+
*/
|
|
43
|
+
recipientPKey: JsonKey;
|
|
53
44
|
}
|
|
54
45
|
/**
|
|
55
46
|
* Ratcheted sending pair is a sending pair with pair ids (pids), attached to
|
|
56
47
|
* it. These ids are used to identify correct key material.
|
|
57
48
|
*/
|
|
58
|
-
export interface RatchetedSendingPair
|
|
49
|
+
export interface RatchetedSendingPair {
|
|
59
50
|
type: 'ratcheted';
|
|
60
51
|
pids: string[];
|
|
61
52
|
timestamp: number;
|
|
@@ -67,6 +58,14 @@ export interface RatchetedSendingPair extends BaseSendingPair {
|
|
|
67
58
|
* and is moved to the sending pair when it is used by the other side.
|
|
68
59
|
*/
|
|
69
60
|
senderKey: JWKeyPair;
|
|
61
|
+
/**
|
|
62
|
+
* This is recipients' public key, to which encryption is done.
|
|
63
|
+
* If this is an introductory pair, this key is recipient's published intro
|
|
64
|
+
* public key.
|
|
65
|
+
* Else, if this is an ratcheted pair, this key comes from crypto material
|
|
66
|
+
* that recipients suggests from time to time for further use.
|
|
67
|
+
*/
|
|
68
|
+
recipientPKey: JsonKeyShort;
|
|
70
69
|
/**
|
|
71
70
|
* This is a precomputed message master key that comes from a given pair.
|
|
72
71
|
* This exist only as a speedup measure, to save time of public key crypto
|
|
@@ -370,6 +370,7 @@ function turnSendingPairToInfo(sp) {
|
|
|
370
370
|
type: 'ratcheted',
|
|
371
371
|
recipientKId: sp.recipientPKey.kid,
|
|
372
372
|
senderKId: sp.senderKey.pkey.kid,
|
|
373
|
+
alg: sp.senderKey.pkey.alg,
|
|
373
374
|
pids,
|
|
374
375
|
timestamp,
|
|
375
376
|
sentMsgs
|
|
@@ -378,7 +379,8 @@ function turnSendingPairToInfo(sp) {
|
|
|
378
379
|
else if (sp.type === 'intro') {
|
|
379
380
|
return {
|
|
380
381
|
type: 'intro',
|
|
381
|
-
recipientKId: sp.recipientPKey.kid
|
|
382
|
+
recipientKId: sp.recipientPKey.kid,
|
|
383
|
+
alg: sp.recipientPKey.alg
|
|
382
384
|
};
|
|
383
385
|
}
|
|
384
386
|
else {
|
|
@@ -389,6 +391,7 @@ function turnReceptionPairToInfo(rp) {
|
|
|
389
391
|
const { pids, timestamp, receivedMsgs, isSenderIntroKey } = rp;
|
|
390
392
|
return {
|
|
391
393
|
pids, timestamp, receivedMsgs, isSenderIntroKey,
|
|
394
|
+
alg: rp.recipientKey.pkey.alg,
|
|
392
395
|
recipientKId: rp.recipientKey.pkey.kid,
|
|
393
396
|
senderKId: rp.senderPKey.kid
|
|
394
397
|
};
|
|
@@ -24,6 +24,7 @@ exports.getMailerIdInfoFor = getMailerIdInfoFor;
|
|
|
24
24
|
const jwkeys_1 = require("../lib-common/jwkeys");
|
|
25
25
|
const url_1 = require("url");
|
|
26
26
|
const request_utils_1 = require("./request-utils");
|
|
27
|
+
const runtime_1 = require("../lib-common/exceptions/runtime");
|
|
27
28
|
async function readJSONLocatedAt(client, url) {
|
|
28
29
|
if ((0, url_1.parse)(url).protocol !== 'https:') {
|
|
29
30
|
throw new Error("Url protocol must be https.");
|
|
@@ -143,23 +144,17 @@ function checkAndPrepareURL(value) {
|
|
|
143
144
|
return 'https://' + value;
|
|
144
145
|
}
|
|
145
146
|
function domainNotFoundExc(address, cause) {
|
|
146
|
-
|
|
147
|
-
runtimeException: true,
|
|
148
|
-
type: 'service-locating',
|
|
149
|
-
address,
|
|
150
|
-
domainNotFound: true,
|
|
151
|
-
cause
|
|
152
|
-
};
|
|
153
|
-
return exc;
|
|
147
|
+
return (0, runtime_1.makeRuntimeException)('service-locating', { address, cause }, { domainNotFound: true });
|
|
154
148
|
}
|
|
155
149
|
function noServiceRecordExc(address) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
150
|
+
return (0, runtime_1.makeRuntimeException)('service-locating', { address }, { noServiceRecord: true });
|
|
151
|
+
}
|
|
152
|
+
function noConnectionExc(cause) {
|
|
153
|
+
return (0, runtime_1.makeRuntimeException)('connect', {
|
|
154
|
+
connectType: 'dns',
|
|
155
|
+
message: `The most likely cause of this error is device not connected. Next likely cause is DNS not setup, or not connecting properly. Like the saying goes: "It's not DNS. There is no way it's DNS. It was DNS."`,
|
|
156
|
+
cause
|
|
157
|
+
}, {});
|
|
163
158
|
}
|
|
164
159
|
/**
|
|
165
160
|
* This implementation extracts exactly one string value for a given service.
|
|
@@ -227,7 +222,8 @@ function getRecordAtStartOf(txt) {
|
|
|
227
222
|
}
|
|
228
223
|
const DNS_ERR_CODE = {
|
|
229
224
|
NODATA: 'ENODATA',
|
|
230
|
-
NOTFOUND: 'ENOTFOUND'
|
|
225
|
+
NOTFOUND: 'ENOTFOUND',
|
|
226
|
+
ESERVFAIL: 'ESERVFAIL'
|
|
231
227
|
};
|
|
232
228
|
Object.freeze(DNS_ERR_CODE);
|
|
233
229
|
function makeServiceLocator(resolver) {
|
|
@@ -247,6 +243,9 @@ function makeServiceLocator(resolver) {
|
|
|
247
243
|
if (code === DNS_ERR_CODE.NODATA) {
|
|
248
244
|
throw noServiceRecordExc(address);
|
|
249
245
|
}
|
|
246
|
+
else if (code === DNS_ERR_CODE.ESERVFAIL) {
|
|
247
|
+
throw noConnectionExc({ code, hostname, message });
|
|
248
|
+
}
|
|
250
249
|
else if (hostname) {
|
|
251
250
|
throw domainNotFoundExc(address, { code, hostname, message });
|
|
252
251
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type ConnectException = web3n.
|
|
1
|
+
export type ConnectException = web3n.HTTPConnectException;
|
|
2
2
|
export type HTTPException = web3n.HTTPException;
|
|
3
|
-
export declare function makeConnectionException(url: string | undefined, method: string | undefined,
|
|
4
|
-
export declare function makeHTTPException(url: string, method: string, status: number,
|
|
3
|
+
export declare function makeConnectionException(url: string | undefined, method: string | undefined, message?: string, cause?: any): ConnectException;
|
|
4
|
+
export declare function makeHTTPException(url: string, method: string, status: number, message?: string, cause?: any): HTTPException;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2015 3NSoft Inc.
|
|
3
|
+
Copyright (C) 2015, 2025 3NSoft Inc.
|
|
4
4
|
|
|
5
5
|
This program is free software: you can redistribute it and/or modify it under
|
|
6
6
|
the terms of the GNU General Public License as published by the Free Software
|
|
@@ -17,31 +17,11 @@
|
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.makeConnectionException = makeConnectionException;
|
|
19
19
|
exports.makeHTTPException = makeHTTPException;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
type: 'http-connect',
|
|
24
|
-
url: url,
|
|
25
|
-
method: method,
|
|
26
|
-
cause
|
|
27
|
-
};
|
|
28
|
-
if (msg) {
|
|
29
|
-
exc.message = msg;
|
|
30
|
-
}
|
|
31
|
-
return exc;
|
|
20
|
+
const runtime_1 = require("./runtime");
|
|
21
|
+
function makeConnectionException(url, method, message, cause) {
|
|
22
|
+
return (0, runtime_1.makeRuntimeException)('connect', { connectType: 'http', url, method, cause, message }, {});
|
|
32
23
|
}
|
|
33
|
-
function makeHTTPException(url, method, status,
|
|
34
|
-
|
|
35
|
-
runtimeException: true,
|
|
36
|
-
type: 'http-request',
|
|
37
|
-
url: url,
|
|
38
|
-
method: method,
|
|
39
|
-
status: status,
|
|
40
|
-
cause
|
|
41
|
-
};
|
|
42
|
-
if (msg) {
|
|
43
|
-
exc.message = msg;
|
|
44
|
-
}
|
|
45
|
-
return exc;
|
|
24
|
+
function makeHTTPException(url, method, status, message, cause) {
|
|
25
|
+
return (0, runtime_1.makeRuntimeException)('http-request', { url, method, status, cause, message }, {});
|
|
46
26
|
}
|
|
47
27
|
Object.freeze(exports);
|