core-3nweb-client-lib 0.27.0 → 0.27.4
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/files.d.ts +56 -26
- package/build/core/asmail/config/index.d.ts +2 -2
- package/build/core/asmail/config/index.js +2 -2
- package/build/core/asmail/config/invitations-anon.d.ts +10 -24
- package/build/core/asmail/config/invitations-anon.js +43 -31
- package/build/core/asmail/config/published-intro-key.d.ts +11 -22
- package/build/core/asmail/config/published-intro-key.js +47 -38
- package/build/core/asmail/inbox/attachments/fs.d.ts +2 -1
- package/build/core/asmail/inbox/attachments/fs.js +4 -3
- package/build/core/asmail/inbox/index.js +2 -2
- package/build/core/asmail/index.d.ts +1 -1
- package/build/core/asmail/index.js +2 -2
- package/build/core/asmail/keyring/correspondent-keys.d.ts +2 -2
- package/build/core/asmail/keyring/correspondent-keys.js +1 -1
- package/build/core/asmail/keyring/index.d.ts +9 -29
- package/build/core/asmail/keyring/index.js +82 -69
- package/build/core/id-manager/index.d.ts +43 -0
- package/build/core/{id-manager.js → id-manager/index.js} +33 -114
- package/build/core/id-manager/key-storage.d.ts +21 -0
- package/build/core/id-manager/key-storage.js +96 -0
- package/build/core/index.js +22 -25
- package/build/core/sign-in.d.ts +1 -2
- package/build/core/sign-in.js +5 -14
- package/build/core/sign-up.d.ts +2 -0
- package/build/core/sign-up.js +2 -1
- package/build/core/storage/index.d.ts +4 -2
- package/build/core/storage/index.js +36 -57
- package/build/core/storage/local/storage.d.ts +1 -1
- package/build/core/storage/synced/obj-files-gc.d.ts +1 -4
- package/build/core/storage/synced/obj-files-gc.js +1 -18
- package/build/core/storage/synced/obj-files.d.ts +11 -1
- package/build/core/storage/synced/obj-files.js +59 -34
- package/build/core/storage/synced/obj-status.d.ts +19 -7
- package/build/core/storage/synced/obj-status.js +158 -83
- package/build/core/storage/synced/storage.d.ts +7 -2
- package/build/core/storage/synced/storage.js +38 -15
- package/build/core/storage/synced/upsyncer.d.ts +4 -4
- package/build/core/storage/synced/upsyncer.js +14 -9
- package/build/ipc-via-protobuf/file.d.ts +7 -0
- package/build/ipc-via-protobuf/file.js +60 -27
- package/build/ipc-via-protobuf/fs.js +55 -38
- package/build/lib-client/3nstorage/exceptions.d.ts +13 -1
- package/build/lib-client/3nstorage/exceptions.js +9 -3
- package/build/lib-client/3nstorage/service.d.ts +6 -2
- package/build/lib-client/3nstorage/service.js +33 -17
- package/build/lib-client/3nstorage/util/file-based-json.js +2 -1
- package/build/lib-client/3nstorage/util/for-arrays.d.ts +1 -0
- package/build/lib-client/3nstorage/util/for-arrays.js +32 -0
- package/build/lib-client/3nstorage/xsp-fs/common.d.ts +5 -4
- package/build/lib-client/3nstorage/xsp-fs/common.js +1 -0
- package/build/lib-client/3nstorage/xsp-fs/file-node.d.ts +5 -10
- package/build/lib-client/3nstorage/xsp-fs/file-node.js +43 -45
- package/build/lib-client/3nstorage/xsp-fs/file.d.ts +7 -6
- package/build/lib-client/3nstorage/xsp-fs/file.js +14 -20
- package/build/lib-client/3nstorage/xsp-fs/folder-node.d.ts +16 -5
- package/build/lib-client/3nstorage/xsp-fs/folder-node.js +238 -68
- package/build/lib-client/3nstorage/xsp-fs/fs.d.ts +18 -17
- package/build/lib-client/3nstorage/xsp-fs/fs.js +32 -37
- package/build/lib-client/3nstorage/xsp-fs/node-in-fs.d.ts +15 -11
- package/build/lib-client/3nstorage/xsp-fs/node-in-fs.js +72 -22
- package/build/lib-client/3nstorage/xsp-fs/xsp-payload-v1.js +1 -1
- package/build/lib-client/local-files/device-fs.js +11 -11
- package/build/lib-client/objs-on-disk/obj-on-disk.d.ts +5 -2
- package/build/lib-client/objs-on-disk/obj-on-disk.js +16 -1
- package/build/lib-client/user-with-mid-session.d.ts +2 -1
- package/build/lib-client/user-with-mid-session.js +7 -1
- package/build/lib-common/async-fs-node.js +8 -8
- package/build/lib-common/exceptions/file.d.ts +4 -2
- package/build/lib-common/exceptions/file.js +24 -58
- package/build/lib-common/ipc/generic-ipc.js +5 -4
- package/build/lib-common/objs-on-disk/file-layout.js +1 -1
- package/build/lib-common/objs-on-disk/utils.js +1 -1
- package/build/lib-common/service-api/3nstorage/owner.d.ts +8 -9
- package/build/lib-common/service-api/3nstorage/owner.js +2 -1
- package/build/protos/asmail.proto.js +5943 -4348
- package/build/protos/file.proto.js +874 -0
- package/build/protos/fs.proto.js +7014 -5419
- package/package.json +3 -2
- package/protos/file.proto +23 -7
- package/protos/fs.proto +27 -13
- package/build/core/id-manager.d.ts +0 -46
package/build/core/index.js
CHANGED
|
@@ -42,17 +42,23 @@ class Core {
|
|
|
42
42
|
this.closingProc = undefined;
|
|
43
43
|
this.initForNewUser = async (u) => {
|
|
44
44
|
// 1) init of id manager without setting fs
|
|
45
|
-
const
|
|
46
|
-
if (!
|
|
45
|
+
const stepTwo = await id_manager_1.IdManager.initWithoutStore(u.address, this.makeResolver('mailerid'), () => this.makeNet(), this.logger.logError, this.logger.logWarning);
|
|
46
|
+
if (!stepTwo) {
|
|
47
|
+
throw new Error(`MailerId server doesn't recognize identity ${u.address}`);
|
|
48
|
+
}
|
|
49
|
+
// 2) complete id manager login, without use of fs
|
|
50
|
+
const idManagerInit = await stepTwo(u.midSKey.default);
|
|
51
|
+
if (!idManagerInit) {
|
|
47
52
|
throw new Error(`Failed to provision MailerId identity`);
|
|
48
53
|
}
|
|
49
|
-
|
|
50
|
-
|
|
54
|
+
const { idManager, setupManagerStorage } = idManagerInit;
|
|
55
|
+
// 3) initialize all storages
|
|
56
|
+
const storesUp = await this.storages.initFreshForNewUser(u.address, idManager.getSigner, u.storeParams, u.storeSKey, this.makeNet, this.makeResolver('3nstorage'), this.logger.logError);
|
|
51
57
|
if (!storesUp) {
|
|
52
58
|
throw new Error(`Stores failed to initialize`);
|
|
53
59
|
}
|
|
54
60
|
// 3) give id manager fs, in which it will record labeled key(s)
|
|
55
|
-
await
|
|
61
|
+
await setupManagerStorage(await this.storages.makeSyncedFSForApp(MAILERID_APP_NAME), [u.midSKey.labeled]);
|
|
56
62
|
return idManager;
|
|
57
63
|
};
|
|
58
64
|
this.initForExistingUserWithoutCache = async (address) => {
|
|
@@ -63,17 +69,18 @@ class Core {
|
|
|
63
69
|
}
|
|
64
70
|
return async (midLoginKey, storageKey) => {
|
|
65
71
|
// 2) complete id manager login, without use of fs
|
|
66
|
-
const
|
|
67
|
-
if (!
|
|
72
|
+
const idManagerInit = await stepTwo(midLoginKey);
|
|
73
|
+
if (!idManagerInit) {
|
|
68
74
|
return;
|
|
69
75
|
}
|
|
76
|
+
const { idManager, setupManagerStorage } = idManagerInit;
|
|
70
77
|
// 3) initialize all storages
|
|
71
78
|
const storeDone = await this.storages.initFromRemote(address, idManager.getSigner, storageKey, this.makeNet, this.makeResolver('3nstorage'), this.logger.logError);
|
|
72
79
|
if (!storeDone) {
|
|
73
80
|
return;
|
|
74
81
|
}
|
|
75
82
|
// 4) complete initialization of id manager
|
|
76
|
-
await
|
|
83
|
+
await setupManagerStorage(await this.storages.makeSyncedFSForApp(MAILERID_APP_NAME));
|
|
77
84
|
return idManager;
|
|
78
85
|
};
|
|
79
86
|
};
|
|
@@ -82,21 +89,12 @@ class Core {
|
|
|
82
89
|
if (!completeStorageInit) {
|
|
83
90
|
return;
|
|
84
91
|
}
|
|
85
|
-
const idManager = await id_manager_1.IdManager.
|
|
86
|
-
if (idManager) {
|
|
87
|
-
|
|
88
|
-
await idManager.setStorages(undefined, await this.storages.makeSyncedFSForApp(MAILERID_APP_NAME));
|
|
89
|
-
return (res ? idManager : undefined);
|
|
92
|
+
const idManager = await id_manager_1.IdManager.initFromCachedStore(address, await this.storages.makeSyncedFSForApp(MAILERID_APP_NAME), this.makeResolver('mailerid'), () => this.makeNet(), this.logger.logError, this.logger.logWarning);
|
|
93
|
+
if (!idManager) {
|
|
94
|
+
return;
|
|
90
95
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (!idManager) {
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
const res = await completeStorageInit(idManager.getSigner);
|
|
97
|
-
await idManager.setStorages(await this.storages.makeLocalFSForApp(MAILERID_APP_NAME), await this.storages.makeSyncedFSForApp(MAILERID_APP_NAME));
|
|
98
|
-
return (res ? idManager : undefined);
|
|
99
|
-
};
|
|
96
|
+
completeStorageInit(idManager.getSigner);
|
|
97
|
+
return idManager;
|
|
100
98
|
};
|
|
101
99
|
this.closeBroadcast = new rxjs_1.Subject();
|
|
102
100
|
this.close$ = this.closeBroadcast.asObservable();
|
|
@@ -112,7 +110,7 @@ class Core {
|
|
|
112
110
|
return core;
|
|
113
111
|
}
|
|
114
112
|
start() {
|
|
115
|
-
const signUp = new sign_up_1.SignUp(this.signUpUrl, this.cryptor.cryptor,
|
|
113
|
+
const signUp = new sign_up_1.SignUp(this.signUpUrl, this.cryptor.cryptor, this.makeNet.bind(this), this.appDirs.getUsersOnDisk, this.logger.logError);
|
|
116
114
|
const signIn = new sign_in_1.SignIn(this.cryptor.cryptor, this.initForExistingUserWithoutCache, this.initForExistingUserWithCache, this.appDirs.getUsersOnDisk, this.logger.logError);
|
|
117
115
|
const capsForStartup = {
|
|
118
116
|
signUp: signUp.exposedService(),
|
|
@@ -227,8 +225,7 @@ function makeStoragePolicy(appDomain, requestedCAPs) {
|
|
|
227
225
|
}
|
|
228
226
|
else if (Array.isArray(capReq.appFS)) {
|
|
229
227
|
const okDomains = capReq.appFS
|
|
230
|
-
.filter(fsInfo => (fsInfo.domain === appDomain) ||
|
|
231
|
-
fsInfo.domain.endsWith('.' + appDomain))
|
|
228
|
+
.filter(fsInfo => (fsInfo.domain === appDomain) || fsInfo.domain.endsWith('.' + appDomain))
|
|
232
229
|
.map(fsInfo => (0, json_utils_1.copy)(fsInfo));
|
|
233
230
|
policy = {
|
|
234
231
|
canOpenAppFS: severalDomainsAppFSChecker(okDomains)
|
package/build/core/sign-in.d.ts
CHANGED
|
@@ -6,8 +6,7 @@ import { LogError } from '../lib-client/logging/log-to-file';
|
|
|
6
6
|
export declare type GenerateKey = (derivParams: ScryptGenParams) => Promise<Uint8Array>;
|
|
7
7
|
export declare type StartInitWithoutCache = (address: string) => Promise<CompleteInitWithoutCache | undefined>;
|
|
8
8
|
export declare type CompleteInitWithoutCache = (midLoginKey: GenerateKey, storageKey: GenerateKey) => Promise<IdManager | undefined>;
|
|
9
|
-
export declare type InitWithCache = (address: string, storageKey: GenerateKey) => Promise<IdManager | undefined
|
|
10
|
-
export declare type InitTwoWithCache = (midLoginKey: GenerateKey) => Promise<IdManager | undefined>;
|
|
9
|
+
export declare type InitWithCache = (address: string, storageKey: GenerateKey) => Promise<IdManager | undefined>;
|
|
11
10
|
declare type SignInService = web3n.startup.SignInService;
|
|
12
11
|
export declare class SignIn {
|
|
13
12
|
private cryptor;
|
package/build/core/sign-in.js
CHANGED
|
@@ -45,7 +45,7 @@ class SignIn {
|
|
|
45
45
|
const midKeyProgressCB = makeKeyGenProgressCB(0, 50, progressCB);
|
|
46
46
|
const midKeyGen = async (params) => (await (0, key_derivation_1.deriveMidKeyPair)(this.cryptor, pass, params, midKeyProgressCB)).skey;
|
|
47
47
|
const storeKeyProgressCB = makeKeyGenProgressCB(51, 100, progressCB);
|
|
48
|
-
const storeKeyGen =
|
|
48
|
+
const storeKeyGen = params => (0, key_derivation_1.deriveStorageSKey)(this.cryptor, pass, params, storeKeyProgressCB);
|
|
49
49
|
const idManager = await this.completeInitWithoutCache(midKeyGen, storeKeyGen);
|
|
50
50
|
if (!idManager) {
|
|
51
51
|
return false;
|
|
@@ -63,23 +63,14 @@ class SignIn {
|
|
|
63
63
|
try {
|
|
64
64
|
const storeKeyProgressCB = makeKeyGenProgressCB(0, 99, progressCB);
|
|
65
65
|
const storeKeyGen = params => (0, key_derivation_1.deriveStorageSKey)(this.cryptor, pass, params, storeKeyProgressCB);
|
|
66
|
-
const
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
if (typeof res === 'object') {
|
|
71
|
-
this.doneBroadcast.next(res);
|
|
66
|
+
const idManager = await this.initWithCache(user, storeKeyGen);
|
|
67
|
+
if (idManager) {
|
|
68
|
+
this.doneBroadcast.next(idManager);
|
|
72
69
|
return true;
|
|
73
70
|
}
|
|
74
|
-
|
|
75
|
-
const midKeyProgressCB = makeKeyGenProgressCB(50, 99, progressCB);
|
|
76
|
-
const midKeyGen = async (params) => (await (0, key_derivation_1.deriveMidKeyPair)(this.cryptor, pass, params, midKeyProgressCB)).skey;
|
|
77
|
-
const idManager = await res(midKeyGen);
|
|
78
|
-
if (!idManager) {
|
|
71
|
+
else {
|
|
79
72
|
return false;
|
|
80
73
|
}
|
|
81
|
-
this.doneBroadcast.next(idManager);
|
|
82
|
-
return true;
|
|
83
74
|
}
|
|
84
75
|
catch (err) {
|
|
85
76
|
throw await this.logAndWrap(err, 'Failing to start in a state with cache');
|
package/build/core/sign-up.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { NetClient } from '../lib-client/request-utils';
|
|
2
2
|
import { JsonKey } from '../lib-common/jwkeys';
|
|
3
|
+
import * as keyDeriv from '../lib-client/key-derivation';
|
|
3
4
|
import { GetUsersOnDisk } from './app-files';
|
|
4
5
|
import { Cryptor } from '../lib-client/cryptor/cryptor';
|
|
5
6
|
import { LogError } from '../lib-client/logging/log-to-file';
|
|
@@ -40,5 +41,6 @@ export interface CreatedUser {
|
|
|
40
41
|
labeled: JsonKey;
|
|
41
42
|
};
|
|
42
43
|
storeSKey: Uint8Array;
|
|
44
|
+
storeParams: keyDeriv.ScryptGenParams;
|
|
43
45
|
}
|
|
44
46
|
export {};
|
package/build/core/sign-up.js
CHANGED
|
@@ -2,6 +2,7 @@ import { GetSigner } from '../id-manager';
|
|
|
2
2
|
import { GenerateKey } from '../sign-in';
|
|
3
3
|
import { StorageGetter } from '../../lib-client/3nstorage/xsp-fs/common';
|
|
4
4
|
import { ServiceLocator } from '../../lib-client/service-locator';
|
|
5
|
+
import { ScryptGenParams } from '../../lib-client/key-derivation';
|
|
5
6
|
import { AsyncSBoxCryptor } from 'xsp-files';
|
|
6
7
|
import { StoragePathForUser } from '../app-files';
|
|
7
8
|
import { LogError } from '../../lib-client/logging/log-to-file';
|
|
@@ -30,8 +31,9 @@ export declare class Storages implements FactoryOfFSs {
|
|
|
30
31
|
* This is a storage getter for links and linking in synced storage.
|
|
31
32
|
*/
|
|
32
33
|
private storageGetterForSyncedStorage;
|
|
33
|
-
startInitFromCache(user: string, keyGen: GenerateKey, makeNet: MakeNet, resolver: ServiceLocator, logError: LogError): Promise<((getSigner: GetSigner) =>
|
|
34
|
-
initFromRemote(user: string, getSigner: GetSigner,
|
|
34
|
+
startInitFromCache(user: string, keyGen: GenerateKey, makeNet: MakeNet, resolver: ServiceLocator, logError: LogError): Promise<((getSigner: GetSigner) => void) | undefined>;
|
|
35
|
+
initFromRemote(user: string, getSigner: GetSigner, generateKey: GenerateKey, makeNet: MakeNet, resolver: ServiceLocator, logError: LogError): Promise<boolean>;
|
|
36
|
+
initFreshForNewUser(user: string, getSigner: GetSigner, params: ScryptGenParams, key: Uint8Array, makeNet: MakeNet, resolver: ServiceLocator, logError: LogError): Promise<boolean>;
|
|
35
37
|
makeSyncedFSForApp(appFolder: string): Promise<WritableFS>;
|
|
36
38
|
makeLocalFSForApp(appFolder: string): Promise<WritableFS>;
|
|
37
39
|
getUserFS(type: StorageType): Promise<FSItem>;
|
|
@@ -85,20 +85,14 @@ async function readRootKeyDerivParamsFromCache(folder) {
|
|
|
85
85
|
throw (0, error_1.errWithCause)(err, `Can't read and parse content of obj status file ${KD_PARAMS_FILE_NAME} in folder ${folder}`);
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
* @param folder
|
|
92
|
-
* @param getFromServer
|
|
93
|
-
*/
|
|
94
|
-
async function getRootKeyDerivParams(folder, getFromServer) {
|
|
95
|
-
let params = await readRootKeyDerivParamsFromCache(folder);
|
|
96
|
-
if (!params) {
|
|
97
|
-
params = await getFromServer();
|
|
98
|
-
await fs.writeFile((0, path_1.join)(folder, KD_PARAMS_FILE_NAME), JSON.stringify(params), { encoding: 'utf8' });
|
|
99
|
-
}
|
|
88
|
+
async function getAndCacheRootKeyDerivParamsFromServer(folder, getFromServer) {
|
|
89
|
+
const params = await getFromServer();
|
|
90
|
+
await saveRootKeyDerivParamsToDisk(folder, params);
|
|
100
91
|
return params;
|
|
101
92
|
}
|
|
93
|
+
async function saveRootKeyDerivParamsToDisk(folder, params) {
|
|
94
|
+
await fs.writeFile((0, path_1.join)(folder, KD_PARAMS_FILE_NAME), JSON.stringify(params), { encoding: 'utf8' });
|
|
95
|
+
}
|
|
102
96
|
class StorageAndFS {
|
|
103
97
|
constructor(storage) {
|
|
104
98
|
this.storage = storage;
|
|
@@ -125,32 +119,15 @@ class StorageAndFS {
|
|
|
125
119
|
}
|
|
126
120
|
}
|
|
127
121
|
}
|
|
128
|
-
static async
|
|
129
|
-
var _a
|
|
122
|
+
static async makeNew(storage, key) {
|
|
123
|
+
var _a;
|
|
130
124
|
const s = new StorageAndFS(storage);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
return s;
|
|
137
|
-
}
|
|
138
|
-
catch (err) {
|
|
139
|
-
if (err.objNotFound) {
|
|
140
|
-
s.rootFS = await fs_1.XspFS.makeNewRoot(s.storage, key);
|
|
141
|
-
await (0, system_folders_1.initSysFolders)(s.rootFS);
|
|
142
|
-
if ((_b = s.rootFS.v) === null || _b === void 0 ? void 0 : _b.sync) {
|
|
143
|
-
s.syncedAppDataRoots = await apps_data_1.AppDataFolders.make(s.rootFS);
|
|
144
|
-
}
|
|
145
|
-
return s;
|
|
146
|
-
}
|
|
147
|
-
else if (err.failedCipherVerification) {
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
throw err;
|
|
152
|
-
}
|
|
125
|
+
s.rootFS = await fs_1.XspFS.makeNewRoot(s.storage, key);
|
|
126
|
+
await (0, system_folders_1.initSysFolders)(s.rootFS);
|
|
127
|
+
if ((_a = s.rootFS.v) === null || _a === void 0 ? void 0 : _a.sync) {
|
|
128
|
+
s.syncedAppDataRoots = await apps_data_1.AppDataFolders.make(s.rootFS);
|
|
153
129
|
}
|
|
130
|
+
return s;
|
|
154
131
|
}
|
|
155
132
|
/**
|
|
156
133
|
* This creates app data folder.
|
|
@@ -278,30 +255,32 @@ class Storages {
|
|
|
278
255
|
if (!this.local) {
|
|
279
256
|
return;
|
|
280
257
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
258
|
+
const { syncedStore, setupRemoteAndStartObjProcs } = await storage_1.SyncedStore.makeAndStartWithoutRemote((0, path_1.join)(storageDir, SYNCED_STORAGE_DIR), user, this.storageGetterForSyncedStorage, this.cryptor, () => resolver(user), makeNet(), logError);
|
|
259
|
+
this.synced = await StorageAndFS.existing(syncedStore, key);
|
|
260
|
+
key.fill(0);
|
|
261
|
+
if (!this.synced) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
return setupRemoteAndStartObjProcs;
|
|
265
|
+
}
|
|
266
|
+
async initFromRemote(user, getSigner, generateKey, makeNet, resolver, logError) {
|
|
267
|
+
const storageDir = this.storageDirForUser(user);
|
|
268
|
+
const { startObjProcs, syncedStore } = await storage_1.SyncedStore.makeAndStart((0, path_1.join)(storageDir, SYNCED_STORAGE_DIR), user, getSigner, this.storageGetterForSyncedStorage, this.cryptor, () => resolver(user), makeNet(), logError);
|
|
269
|
+
const params = await getAndCacheRootKeyDerivParamsFromServer(storageDir, syncedStore.getRootKeyDerivParamsFromServer);
|
|
270
|
+
const key = await generateKey(params);
|
|
271
|
+
this.synced = await StorageAndFS.existing(syncedStore, key);
|
|
272
|
+
this.local = await StorageAndFS.makeNew(await storage_2.LocalStorage.makeAndStart((0, path_1.join)(storageDir, LOCAL_STORAGE_DIR), this.storageGetterForLocalStorage, this.cryptor, logError), key);
|
|
273
|
+
key.fill(0);
|
|
274
|
+
startObjProcs();
|
|
275
|
+
return (!!this.synced && !!this.local);
|
|
294
276
|
}
|
|
295
|
-
async
|
|
277
|
+
async initFreshForNewUser(user, getSigner, params, key, makeNet, resolver, logError) {
|
|
296
278
|
const storageDir = this.storageDirForUser(user);
|
|
297
279
|
const { startObjProcs, syncedStore } = await storage_1.SyncedStore.makeAndStart((0, path_1.join)(storageDir, SYNCED_STORAGE_DIR), user, getSigner, this.storageGetterForSyncedStorage, this.cryptor, () => resolver(user), makeNet(), logError);
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
const key = ((typeof keyOrGen === 'function') ?
|
|
301
|
-
await keyOrGen(params) : keyOrGen);
|
|
302
|
-
this.synced = await StorageAndFS.newOrExisting(syncedStore, key);
|
|
303
|
-
this.local = await StorageAndFS.newOrExisting(await storage_2.LocalStorage.makeAndStart((0, path_1.join)(storageDir, LOCAL_STORAGE_DIR), this.storageGetterForLocalStorage, this.cryptor, logError), key);
|
|
280
|
+
this.synced = await StorageAndFS.makeNew(syncedStore, key);
|
|
281
|
+
this.local = await StorageAndFS.makeNew(await storage_2.LocalStorage.makeAndStart((0, path_1.join)(storageDir, LOCAL_STORAGE_DIR), this.storageGetterForLocalStorage, this.cryptor, logError), key);
|
|
304
282
|
key.fill(0);
|
|
283
|
+
await saveRootKeyDerivParamsToDisk(storageDir, params);
|
|
305
284
|
startObjProcs();
|
|
306
285
|
return (!!this.synced && !!this.local);
|
|
307
286
|
}
|
|
@@ -523,7 +502,7 @@ async function applyPolicyToFSCollection(c, policy, path) {
|
|
|
523
502
|
}
|
|
524
503
|
const nameAndItem = await (0, async_iter_1.asyncFind)(await c.entries(), async (v) => path.startsWith(v[0]));
|
|
525
504
|
if (!nameAndItem) {
|
|
526
|
-
throw (0, file_1.makeFileException)(
|
|
505
|
+
throw (0, file_1.makeFileException)('notFound', path);
|
|
527
506
|
}
|
|
528
507
|
const [name, item] = nameAndItem;
|
|
529
508
|
path = path.substring(name.length);
|
|
@@ -9,7 +9,7 @@ export declare class LocalStorage implements Storage {
|
|
|
9
9
|
private readonly files;
|
|
10
10
|
private readonly getStorages;
|
|
11
11
|
readonly cryptor: AsyncSBoxCryptor;
|
|
12
|
-
|
|
12
|
+
readonly logError: LogError;
|
|
13
13
|
readonly type = "local";
|
|
14
14
|
readonly versioned = true;
|
|
15
15
|
readonly nodes: NodesContainer;
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { SynchronizerOnObjId, SyncedObj } from './obj-files';
|
|
2
|
-
import { StorageOwner as RemoteStorage } from '../../../lib-client/3nstorage/service';
|
|
3
2
|
export declare class GC {
|
|
4
3
|
private readonly sync;
|
|
5
4
|
private readonly rmObjFromCache;
|
|
6
5
|
private readonly rmObjFolder;
|
|
7
|
-
private readonly remote;
|
|
8
6
|
private isStopped;
|
|
9
7
|
/**
|
|
10
8
|
* All gc steps are done in this process.
|
|
@@ -20,11 +18,10 @@ export declare class GC {
|
|
|
20
18
|
* with wip set.
|
|
21
19
|
*/
|
|
22
20
|
private scheduled;
|
|
23
|
-
constructor(sync: SynchronizerOnObjId, rmObjFromCache: (obj: SyncedObj) => void, rmObjFolder: (objId: string) => Promise<void
|
|
21
|
+
constructor(sync: SynchronizerOnObjId, rmObjFromCache: (obj: SyncedObj) => void, rmObjFolder: (objId: string) => Promise<void>);
|
|
24
22
|
scheduleCollection: (obj: SyncedObj) => void;
|
|
25
23
|
stop(): Promise<void>;
|
|
26
24
|
private objCollecting;
|
|
27
25
|
private collectIn;
|
|
28
|
-
private upsyncObjRemovalWhenNeeded;
|
|
29
26
|
private checkAndRemoveWholeObjFolder;
|
|
30
27
|
}
|
|
@@ -24,11 +24,10 @@ const path_1 = require("path");
|
|
|
24
24
|
const utils_1 = require("../common/utils");
|
|
25
25
|
const upload_header_file_1 = require("./upload-header-file");
|
|
26
26
|
class GC {
|
|
27
|
-
constructor(sync, rmObjFromCache, rmObjFolder
|
|
27
|
+
constructor(sync, rmObjFromCache, rmObjFolder) {
|
|
28
28
|
this.sync = sync;
|
|
29
29
|
this.rmObjFromCache = rmObjFromCache;
|
|
30
30
|
this.rmObjFolder = rmObjFolder;
|
|
31
|
-
this.remote = remote;
|
|
32
31
|
this.isStopped = false;
|
|
33
32
|
/**
|
|
34
33
|
* All gc steps are done in this process.
|
|
@@ -71,27 +70,11 @@ class GC {
|
|
|
71
70
|
this.isStopped = true;
|
|
72
71
|
}
|
|
73
72
|
async collectIn(obj) {
|
|
74
|
-
if (obj.statusObj().isArchived()) {
|
|
75
|
-
await this.upsyncObjRemovalWhenNeeded(obj);
|
|
76
|
-
}
|
|
77
73
|
const nonGarbage = obj.statusObj().getNonGarbageVersions();
|
|
78
74
|
if (!(await this.checkAndRemoveWholeObjFolder(obj, nonGarbage))) {
|
|
79
75
|
await removeGarbageFiles(obj, nonGarbage);
|
|
80
76
|
}
|
|
81
77
|
}
|
|
82
|
-
async upsyncObjRemovalWhenNeeded(obj) {
|
|
83
|
-
if (!needsUpsyncOfRemoval(obj)) {
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
try {
|
|
87
|
-
await this.remote.deleteObj(obj.objId);
|
|
88
|
-
}
|
|
89
|
-
catch (exc) {
|
|
90
|
-
// XXX will need to schedule other attempt to delete on remote
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
await obj.statusObj().recordSyncOfObjRemoval();
|
|
94
|
-
}
|
|
95
78
|
async checkAndRemoveWholeObjFolder(obj, { local, remote }) {
|
|
96
79
|
if (obj.objId
|
|
97
80
|
&& obj.statusObj().isArchived()
|
|
@@ -13,6 +13,12 @@ import { StorageOwner as RemoteStorage } from '../../../lib-client/3nstorage/ser
|
|
|
13
13
|
import { UploadHeaderChange } from '../../../lib-client/3nstorage/xsp-fs/common';
|
|
14
14
|
export declare const UNSYNCED_FILE_NAME_EXT = "unsynced";
|
|
15
15
|
export declare const REMOTE_FILE_NAME_EXT = "v";
|
|
16
|
+
/**
|
|
17
|
+
* File system has nodes. Each node may have data in one or many objects of
|
|
18
|
+
* storage. SyncedObj allows to work with files of storage object, even when
|
|
19
|
+
* file system node no longer exists. ObjFiles is a holder and factory of
|
|
20
|
+
* SyncedObj's.
|
|
21
|
+
*/
|
|
16
22
|
export declare class ObjFiles {
|
|
17
23
|
private readonly folders;
|
|
18
24
|
private readonly logError;
|
|
@@ -22,6 +28,7 @@ export declare class ObjFiles {
|
|
|
22
28
|
private readonly gc;
|
|
23
29
|
private constructor();
|
|
24
30
|
static makeFor(path: string, remote: RemoteStorage, logError: LogError): Promise<ObjFiles>;
|
|
31
|
+
private canMoveObjToDeeperCache;
|
|
25
32
|
findObj(objId: ObjId): Promise<SyncedObj | undefined>;
|
|
26
33
|
getObjInCache(objId: ObjId): SyncedObj | undefined;
|
|
27
34
|
private makeObj;
|
|
@@ -31,7 +38,7 @@ export declare class ObjFiles {
|
|
|
31
38
|
fileWrite$: Observable<FileWrite[]>;
|
|
32
39
|
newObj: SyncedObj;
|
|
33
40
|
}>;
|
|
34
|
-
|
|
41
|
+
findObjsToRemoveOnRemote(): Observable<ObjId>;
|
|
35
42
|
scheduleGC(obj: SyncedObj): void;
|
|
36
43
|
}
|
|
37
44
|
export declare type SynchronizerOnObjId = <T>(objId: ObjId, action: () => Promise<T>) => Promise<T>;
|
|
@@ -81,4 +88,7 @@ export declare class SyncedObj {
|
|
|
81
88
|
}>;
|
|
82
89
|
syncStatus(): SyncedObjStatus;
|
|
83
90
|
statusObj(): ObjStatus;
|
|
91
|
+
recordRemovalUploadAndGC(): Promise<void>;
|
|
92
|
+
isRemoteVersionOnDisk(version: number): Promise<'complete' | 'partial' | 'none'>;
|
|
93
|
+
downloadRemoteVersion(version: number): Promise<void>;
|
|
84
94
|
}
|
|
@@ -19,7 +19,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
19
19
|
exports.SyncedObj = exports.ObjFiles = exports.REMOTE_FILE_NAME_EXT = exports.UNSYNCED_FILE_NAME_EXT = void 0;
|
|
20
20
|
const rxjs_1 = require("rxjs");
|
|
21
21
|
const synced_1 = require("../../../lib-common/processes/synced");
|
|
22
|
-
const sleep_1 = require("../../../lib-common/processes/sleep");
|
|
23
22
|
const obj_folders_1 = require("../../../lib-client/objs-on-disk/obj-folders");
|
|
24
23
|
const fs = require("../../../lib-common/async-fs-node");
|
|
25
24
|
const obj_on_disk_1 = require("../../../lib-client/objs-on-disk/obj-on-disk");
|
|
@@ -33,8 +32,15 @@ const obj_status_1 = require("./obj-status");
|
|
|
33
32
|
const timed_cache_1 = require("../../../lib-common/timed-cache");
|
|
34
33
|
const upload_header_file_1 = require("./upload-header-file");
|
|
35
34
|
const utils_1 = require("../common/utils");
|
|
35
|
+
const exceptions_1 = require("../../../lib-client/3nstorage/exceptions");
|
|
36
36
|
exports.UNSYNCED_FILE_NAME_EXT = 'unsynced';
|
|
37
37
|
exports.REMOTE_FILE_NAME_EXT = 'v';
|
|
38
|
+
/**
|
|
39
|
+
* File system has nodes. Each node may have data in one or many objects of
|
|
40
|
+
* storage. SyncedObj allows to work with files of storage object, even when
|
|
41
|
+
* file system node no longer exists. ObjFiles is a holder and factory of
|
|
42
|
+
* SyncedObj's.
|
|
43
|
+
*/
|
|
38
44
|
class ObjFiles {
|
|
39
45
|
constructor(folders, remote, logError) {
|
|
40
46
|
this.folders = folders;
|
|
@@ -46,31 +52,32 @@ class ObjFiles {
|
|
|
46
52
|
if (this.objs.get(obj.objId) === obj) {
|
|
47
53
|
this.objs.delete(obj.objId);
|
|
48
54
|
}
|
|
49
|
-
}, objId => this.folders.removeFolderOf(objId)
|
|
55
|
+
}, objId => this.folders.removeFolderOf(objId));
|
|
50
56
|
Object.freeze(this);
|
|
51
57
|
}
|
|
52
58
|
static async makeFor(path, remote, logError) {
|
|
53
|
-
const canMove =
|
|
54
|
-
if (objFiles.objs.has(objId)) {
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
const lst = await fs.readdir(objFolderPath);
|
|
58
|
-
for (const fName of lst) {
|
|
59
|
-
if (fName.endsWith(exports.UNSYNCED_FILE_NAME_EXT)) {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
try {
|
|
64
|
-
return (await obj_status_1.ObjStatus.fileShowsObjNotInSyncedState(objFolderPath, objId));
|
|
65
|
-
}
|
|
66
|
-
catch (exc) {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
};
|
|
59
|
+
const canMove = (objId, objFolderPath) => objFiles.canMoveObjToDeeperCache(objId, objFolderPath);
|
|
70
60
|
const folders = await obj_folders_1.ObjFolders.makeWithGenerations(path, canMove, logError);
|
|
71
61
|
const objFiles = new ObjFiles(folders, remote, logError);
|
|
72
62
|
return objFiles;
|
|
73
63
|
}
|
|
64
|
+
async canMoveObjToDeeperCache(objId, objFolderPath) {
|
|
65
|
+
if (this.objs.has(objId)) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
const lst = await fs.readdir(objFolderPath);
|
|
69
|
+
for (const fName of lst) {
|
|
70
|
+
if (fName.endsWith(exports.UNSYNCED_FILE_NAME_EXT)) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
return (await obj_status_1.ObjStatus.fileShowsObjNotInSyncedState(objFolderPath, objId));
|
|
76
|
+
}
|
|
77
|
+
catch (exc) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
74
81
|
async findObj(objId) {
|
|
75
82
|
let obj = this.objs.get(objId);
|
|
76
83
|
if (obj) {
|
|
@@ -131,25 +138,23 @@ class ObjFiles {
|
|
|
131
138
|
.pipe((0, utils_for_observables_1.flatTap)(undefined, err => this.removeFailedNewObj(newObj)));
|
|
132
139
|
return { fileWrite$, newObj };
|
|
133
140
|
}
|
|
134
|
-
|
|
141
|
+
findObjsToRemoveOnRemote() {
|
|
135
142
|
return (0, rxjs_1.from)([undefined])
|
|
136
143
|
.pipe(
|
|
137
144
|
// listing recent folders, exactly once
|
|
138
145
|
(0, operators_1.mergeMap)(() => this.folders.listRecent()),
|
|
139
146
|
// flatten array and space it in time, to process folders one by one
|
|
140
|
-
(0, operators_1.mergeMap)(objsAndPaths => objsAndPaths), (0, operators_1.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
(0, operators_1.mergeMap)(({ path, objId }) => this.sync(objId, async () => {
|
|
146
|
-
if (this.objs.has(objId)) {
|
|
147
|
-
return;
|
|
147
|
+
(0, operators_1.mergeMap)(objsAndPaths => objsAndPaths), (0, operators_1.mergeMap)(async ({ objId, path }) => {
|
|
148
|
+
const obj = this.objs.get(objId);
|
|
149
|
+
if (obj) {
|
|
150
|
+
return (obj.statusObj().needsRemovalOnRemote() ?
|
|
151
|
+
objId : undefined);
|
|
148
152
|
}
|
|
149
|
-
|
|
150
|
-
.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
+
else {
|
|
154
|
+
const needsRm = await obj_status_1.ObjStatus.fileShowsObjNeedsRemovalOnRemote(path, objId);
|
|
155
|
+
return (needsRm ? objId : undefined);
|
|
156
|
+
}
|
|
157
|
+
}, 1), (0, operators_1.filter)(objId => (objId !== undefined)));
|
|
153
158
|
}
|
|
154
159
|
scheduleGC(obj) {
|
|
155
160
|
this.gc.scheduleCollection(obj);
|
|
@@ -334,9 +339,10 @@ class SyncedObj {
|
|
|
334
339
|
this.remoteVers.set(uploadVersion, syncedVerObj);
|
|
335
340
|
}
|
|
336
341
|
else {
|
|
337
|
-
|
|
342
|
+
const localPath = this.localVerPath(localVersion);
|
|
343
|
+
await fs.rename(localPath, remotePath);
|
|
338
344
|
}
|
|
339
|
-
await this.status.
|
|
345
|
+
await this.status.recordUploadCompletion(localVersion, uploadVersion);
|
|
340
346
|
this.scheduleSelfGC();
|
|
341
347
|
}
|
|
342
348
|
dropCachedLocalObjVersionsLessOrEqual(version) {
|
|
@@ -387,6 +393,25 @@ class SyncedObj {
|
|
|
387
393
|
statusObj() {
|
|
388
394
|
return this.status;
|
|
389
395
|
}
|
|
396
|
+
async recordRemovalUploadAndGC() {
|
|
397
|
+
await this.status.recordRemoteRemovalCompletion();
|
|
398
|
+
this.scheduleSelfGC();
|
|
399
|
+
}
|
|
400
|
+
async isRemoteVersionOnDisk(version) {
|
|
401
|
+
if (!this.status.isAmongRemote(version)) {
|
|
402
|
+
throw (0, exceptions_1.makeObjVersionNotFoundExc)(this.objId, version);
|
|
403
|
+
}
|
|
404
|
+
const verPath = this.remoteVerPath(version);
|
|
405
|
+
if (!(await isOnDisk(verPath))) {
|
|
406
|
+
return 'none';
|
|
407
|
+
}
|
|
408
|
+
const objVer = await this.instanceOfRemoteObjVer(version);
|
|
409
|
+
return (objVer.doesFileNeedDownload() ? 'complete' : 'partial');
|
|
410
|
+
}
|
|
411
|
+
async downloadRemoteVersion(version) {
|
|
412
|
+
const objVer = await this.instanceOfRemoteObjVer(version);
|
|
413
|
+
await objVer.downloadMissingSections();
|
|
414
|
+
}
|
|
390
415
|
}
|
|
391
416
|
exports.SyncedObj = SyncedObj;
|
|
392
417
|
Object.freeze(SyncedObj.prototype);
|