spec-3nweb-server 1.3.8 → 1.5.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/3nstorage/3nstorage-app.js +4 -4
- package/build/3nstorage/owner.js +28 -28
- package/build/3nstorage/resources/store.d.ts +2 -9
- package/build/3nstorage/resources/store.js +76 -73
- package/build/3nstorage/resources/users.d.ts +4 -2
- package/build/3nstorage/resources/users.js +8 -4
- package/build/3nstorage/routes/owner/archive-obj-version.d.ts +2 -2
- package/build/3nstorage/routes/owner/archive-obj-version.js +36 -31
- package/build/3nstorage/routes/owner/cancel-trans.js +1 -1
- package/build/3nstorage/routes/owner/delete-obj.d.ts +3 -2
- package/build/3nstorage/routes/owner/delete-obj.js +42 -7
- package/build/3nstorage/routes/owner/get-archived-obj-ver.js +10 -6
- package/build/3nstorage/routes/owner/get-current-obj.js +2 -2
- package/build/3nstorage/routes/owner/list-obj-archive.js +28 -31
- package/build/3nstorage/routes/owner/param-getter.js +3 -2
- package/build/3nstorage/routes/owner/param-setter.js +3 -2
- package/build/3nstorage/routes/owner/put-current-obj.js +12 -10
- package/build/3nstorage/routes/owner/session-params.js +4 -3
- package/build/admin/admin-app.js +5 -5
- package/build/admin/resources/users.js +42 -42
- package/build/admin/routes/add.js +3 -3
- package/build/admin/signup-tokens.js +8 -8
- package/build/asmail/asmail-app.js +7 -7
- package/build/asmail/config.js +9 -8
- package/build/asmail/delivery.js +10 -9
- package/build/asmail/resources/delivery-sessions.js +4 -3
- package/build/asmail/resources/inbox.d.ts +1 -1
- package/build/asmail/resources/inbox.js +22 -22
- package/build/asmail/resources/recipients.d.ts +2 -1
- package/build/asmail/resources/recipients.js +4 -4
- package/build/asmail/resources/sessions.js +2 -1
- package/build/asmail/retrieval.js +13 -8
- package/build/asmail/routes/config/param-getter.js +3 -2
- package/build/asmail/routes/config/param-setter.js +3 -2
- package/build/asmail/routes/delivery/finalize-delivery.js +3 -2
- package/build/asmail/routes/delivery/pre-flight.js +5 -4
- package/build/asmail/routes/delivery/provide-recipient-pubkey.js +3 -2
- package/build/asmail/routes/delivery/put-metadata.js +3 -2
- package/build/asmail/routes/delivery/put-obj.js +4 -4
- package/build/asmail/routes/delivery/restart-session.js +4 -3
- package/build/asmail/routes/delivery/sender-authorization.d.ts +1 -3
- package/build/asmail/routes/delivery/sender-authorization.js +3 -2
- package/build/asmail/routes/delivery/start-session.js +5 -4
- package/build/asmail/routes/retrieval/get-message-meta.js +3 -2
- package/build/asmail/routes/retrieval/get-message-obj.js +4 -3
- package/build/asmail/routes/retrieval/list-messages.js +3 -2
- package/build/asmail/routes/retrieval/remove-message.js +3 -2
- package/build/lib-common/async-fs-node.d.ts +2 -0
- package/build/lib-common/async-fs-node.js +13 -13
- package/build/lib-common/byte-streaming/common.js +9 -9
- package/build/lib-common/canonical-address.js +1 -1
- package/build/lib-common/ipc/generic-ipc.js +12 -12
- package/build/lib-common/ipc/ws-ipc.js +2 -2
- package/build/lib-common/mid-sigs-NaCl-Ed.js +14 -14
- package/build/lib-common/objs-on-disk/file-layout.js +10 -10
- package/build/lib-common/objs-on-disk/obj-file.js +11 -11
- package/build/lib-common/objs-on-disk/utils.d.ts +1 -0
- package/build/lib-common/objs-on-disk/utils.js +3 -3
- package/build/lib-common/processes.js +1 -1
- package/build/lib-common/random-node.js +7 -7
- package/build/lib-common/service-api/3nstorage/owner.d.ts +24 -18
- package/build/lib-common/service-api/3nstorage/owner.js +31 -26
- package/build/lib-common/service-api/asmail/delivery.js +2 -2
- package/build/lib-common/service-api/asmail/retrieval.js +1 -1
- package/build/lib-server/conf-util.js +2 -1
- package/build/lib-server/middleware/body-parsers.js +16 -16
- package/build/lib-server/middleware/error-handler.js +1 -1
- package/build/lib-server/resources/mailerid-authorizer.js +3 -3
- package/build/lib-server/resources/mem-backed-sessions-factory.js +3 -3
- package/build/lib-server/resources/server-data-folders.js +23 -23
- package/build/lib-server/resources/sessions.js +5 -5
- package/build/lib-server/resources/user-files.js +8 -8
- package/build/lib-server/routes/pub-key-login/complete-exchange.js +4 -3
- package/build/lib-server/routes/pub-key-login/start-exchange.js +7 -6
- package/build/lib-server/routes/sessions/mid-auth.js +6 -5
- package/build/lib-server/routes/sessions/start.js +4 -3
- package/build/lib-server/web-sockets/app.d.ts +1 -0
- package/build/lib-server/web-sockets/app.js +6 -5
- package/build/lib-server/web-sockets/server-events.js +5 -4
- package/build/mailerId/mailerId-app.js +7 -7
- package/build/mailerId/resources/certifier.d.ts +4 -6
- package/build/mailerId/resources/certifier.js +8 -7
- package/build/mailerId/resources/compute-login-dhshared-key.js +2 -1
- package/build/mailerId/resources/sessions.js +2 -1
- package/build/mailerId/resources/users.js +4 -4
- package/build/mailerId/routes/certify.js +1 -1
- package/build/main.js +10 -10
- package/build/mock/dns.js +1 -1
- package/build/mock/mock-as-child-proc.js +10 -10
- package/build/mock/node-child-ipc.js +2 -2
- package/build/mock/run-in-proc.js +7 -7
- package/build/run-config.js +10 -10
- package/build/run.js +4 -4
- package/build/services.js +5 -5
- package/package.json +13 -10
|
@@ -44,13 +44,13 @@ function setupStaticEntryRoute(app) {
|
|
|
44
44
|
}
|
|
45
45
|
function makeApp(dataFolder, domain, midAuthorizer) {
|
|
46
46
|
const app = new app_1.AppWithWSs();
|
|
47
|
-
const ownersSessions = sessions_1.makeSessionFactory(20 * 60);
|
|
48
|
-
const sharingSessions = sessions_1.makeSessionFactory(20 * 60);
|
|
49
|
-
const users = users_1.makeFactory(dataFolder);
|
|
47
|
+
const ownersSessions = (0, sessions_1.makeSessionFactory)(20 * 60);
|
|
48
|
+
const sharingSessions = (0, sessions_1.makeSessionFactory)(20 * 60);
|
|
49
|
+
const users = (0, users_1.makeFactory)(dataFolder);
|
|
50
50
|
setupStaticEntryRoute(app.http);
|
|
51
51
|
app.use(PATHS.owner, owners.makeApp(domain, ownersSessions, users, midAuthorizer));
|
|
52
52
|
app.http.use(PATHS.shared, sharing.makeApp(sharingSessions, users));
|
|
53
|
-
app.http.use(error_handler_1.makeErrHandler((err, req) => {
|
|
53
|
+
app.http.use((0, error_handler_1.makeErrHandler)((err, req) => {
|
|
54
54
|
if (typeof err.status !== 'number') {
|
|
55
55
|
console.error(`\n --- Error occured in storage, when handling ${req.method} request to ${req.originalUrl}`);
|
|
56
56
|
console.error(err);
|
package/build/3nstorage/owner.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2015 - 2017 3NSoft Inc.
|
|
3
|
+
Copyright (C) 2015 - 2017, 2022 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
|
|
@@ -59,44 +59,44 @@ const MAX_CHUNK_SIZE = '0.5mb';
|
|
|
59
59
|
function setHttpPart(app, domain, sessions, users, midAuthorizer) {
|
|
60
60
|
app.http.disable('etag');
|
|
61
61
|
// Login
|
|
62
|
-
app.http.post('/' + api.midLogin.START_URL_END, sessions.checkSession(), body_parsers_1.json('1kb'), start_1.startSession(users.exists, sessions.generate));
|
|
63
|
-
app.http.post('/' + api.midLogin.AUTH_URL_END, sessions.ensureOpenedSession(), body_parsers_1.json('4kb'), mid_auth_1.midLogin(domain, midAuthorizer));
|
|
62
|
+
app.http.post('/' + api.midLogin.START_URL_END, sessions.checkSession(), (0, body_parsers_1.json)('1kb'), (0, start_1.startSession)(users.exists, sessions.generate));
|
|
63
|
+
app.http.post('/' + api.midLogin.AUTH_URL_END, sessions.ensureOpenedSession(), (0, body_parsers_1.json)('4kb'), (0, mid_auth_1.midLogin)(domain, midAuthorizer));
|
|
64
64
|
// *** Require authorized session for everything below ***
|
|
65
65
|
app.http.use(sessions.ensureAuthorizedSession());
|
|
66
|
-
app.http.post('/' + api.closeSession.URL_END, body_parsers_1.emptyBody(), close_1.closeSession());
|
|
66
|
+
app.http.post('/' + api.closeSession.URL_END, (0, body_parsers_1.emptyBody)(), (0, close_1.closeSession)());
|
|
67
67
|
// Session params
|
|
68
|
-
app.http.get('/' + api.sessionParams.URL_END, session_params_1.sessionParams(MAX_CHUNK_SIZE));
|
|
68
|
+
app.http.get('/' + api.sessionParams.URL_END, (0, session_params_1.sessionParams)(MAX_CHUNK_SIZE));
|
|
69
69
|
// Key derivation params
|
|
70
70
|
app.http.route('/' + api.keyDerivParams.URL_END)
|
|
71
|
-
.get(param_getter_1.getParam(users.getKeyDerivParams))
|
|
72
|
-
.put(body_parsers_1.json('1kb'), param_setter_1.setParam(users.setKeyDerivParams));
|
|
71
|
+
.get((0, param_getter_1.getParam)(users.getKeyDerivParams))
|
|
72
|
+
.put((0, body_parsers_1.json)('1kb'), (0, param_setter_1.setParam)(users.setKeyDerivParams));
|
|
73
73
|
// Transaction canceling
|
|
74
|
-
app.http.post('/' + api.cancelTransaction.EXPRESS_URL_END, body_parsers_1.emptyBody(), cancel_trans_1.cancelTransaction(false, users.cancelTransaction));
|
|
75
|
-
app.http.post('/' + api.cancelRootTransaction.EXPRESS_URL_END, body_parsers_1.emptyBody(), cancel_trans_1.cancelTransaction(true, users.cancelTransaction));
|
|
76
|
-
// Getting current root object
|
|
74
|
+
app.http.post('/' + api.cancelTransaction.EXPRESS_URL_END, (0, body_parsers_1.emptyBody)(), (0, cancel_trans_1.cancelTransaction)(false, users.cancelTransaction));
|
|
75
|
+
app.http.post('/' + api.cancelRootTransaction.EXPRESS_URL_END, (0, body_parsers_1.emptyBody)(), (0, cancel_trans_1.cancelTransaction)(true, users.cancelTransaction));
|
|
76
|
+
// Getting and updating current root object
|
|
77
77
|
app.http.route('/' + api.currentRootObj.EXPRESS_URL_END)
|
|
78
|
-
.get(get_current_obj_1.getCurrentObj(true, users.getCurrentRootObj))
|
|
79
|
-
.put(put_current_obj_1.saveCurrentObj(true, users.saveNewRootVersion, MAX_CHUNK_SIZE));
|
|
80
|
-
// Getting current non-root objects
|
|
78
|
+
.get((0, get_current_obj_1.getCurrentObj)(true, users.getCurrentRootObj))
|
|
79
|
+
.put((0, put_current_obj_1.saveCurrentObj)(true, users.saveNewRootVersion, MAX_CHUNK_SIZE));
|
|
80
|
+
// Getting, updating and removing current non-root objects
|
|
81
81
|
app.http.route('/' + api.currentObj.EXPRESS_URL_END)
|
|
82
|
-
.get(get_current_obj_1.getCurrentObj(false, users.getCurrentObj))
|
|
83
|
-
.delete(delete_obj_1.
|
|
84
|
-
.put(put_current_obj_1.saveCurrentObj(false, users.saveNewObjVersion, MAX_CHUNK_SIZE));
|
|
82
|
+
.get((0, get_current_obj_1.getCurrentObj)(false, users.getCurrentObj))
|
|
83
|
+
.delete((0, delete_obj_1.deleteCurrentObjVer)(users.deleteCurrentObjVersion))
|
|
84
|
+
.put((0, put_current_obj_1.saveCurrentObj)(false, users.saveNewObjVersion, MAX_CHUNK_SIZE));
|
|
85
|
+
// Getting root archived versions
|
|
86
|
+
app.http.route('/' + api.archivedRootVersion.EXPRESS_URL_END)
|
|
87
|
+
.get((0, get_archived_obj_ver_1.getArchivedObjVersion)(true, users.getArchivedRootVersion));
|
|
88
|
+
// Getting non-root object archived versions
|
|
89
|
+
app.http.route('/' + api.archivedObjVersion.EXPRESS_URL_END)
|
|
90
|
+
.get((0, get_archived_obj_ver_1.getArchivedObjVersion)(false, users.getArchivedObjVersion));
|
|
85
91
|
// Archive root's current version
|
|
86
92
|
app.http.route('/' + api.archiveRoot.URL_END)
|
|
87
|
-
.get(list_obj_archive_1.listObjArchive(true, users.listObjArchive))
|
|
88
|
-
.
|
|
93
|
+
.get((0, list_obj_archive_1.listObjArchive)(true, users.listObjArchive))
|
|
94
|
+
.post((0, body_parsers_1.emptyBody)(), (0, archive_obj_version_1.archiveCurrentObjVersion)(true, users.archiveObjVersion))
|
|
95
|
+
.delete((0, delete_obj_1.deleteArchivedObjVer)(true, users.deleteArchivedObjVersion));
|
|
89
96
|
// Archive non-root object's current version
|
|
90
97
|
app.http.route('/' + api.archiveObj.EXPRESS_URL_END)
|
|
91
|
-
.get(list_obj_archive_1.listObjArchive(false, users.listObjArchive))
|
|
92
|
-
.
|
|
93
|
-
|
|
94
|
-
app.http.route('/' + api.archivedRootVersion.EXPRESS_URL_END)
|
|
95
|
-
.get(get_archived_obj_ver_1.getArchivedObjVersion(true, users.getArchivedRootVersion))
|
|
96
|
-
.delete(delete_obj_1.deleteObj(true, false, users.deleteObj));
|
|
97
|
-
// Removing archived and current versions of non-root object
|
|
98
|
-
app.http.route('/' + api.archivedObjVersion.EXPRESS_URL_END)
|
|
99
|
-
.get(get_archived_obj_ver_1.getArchivedObjVersion(true, users.getArchivedObjVersion))
|
|
100
|
-
.delete(delete_obj_1.deleteObj(false, false, users.deleteObj));
|
|
98
|
+
.get((0, list_obj_archive_1.listObjArchive)(false, users.listObjArchive))
|
|
99
|
+
.post((0, body_parsers_1.emptyBody)(), (0, archive_obj_version_1.archiveCurrentObjVersion)(false, users.archiveObjVersion))
|
|
100
|
+
.delete((0, delete_obj_1.deleteArchivedObjVer)(false, users.deleteArchivedObjVersion));
|
|
101
101
|
}
|
|
102
102
|
Object.freeze(exports);
|
|
@@ -102,15 +102,8 @@ export declare class Store extends UserFiles {
|
|
|
102
102
|
getArchivedObjVersion(objId: string | null, version: number, header: boolean, segsOffset: number, segsLimit: number | undefined): Promise<ObjReader>;
|
|
103
103
|
private makeObjReader;
|
|
104
104
|
private getObjFile;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
* root object.
|
|
108
|
-
* @param archVersion is an optional parameter, identifying archived version
|
|
109
|
-
* to delete. Default null value indicates that an object should be removed.
|
|
110
|
-
* If an object has any archived versions (even if current), these will not
|
|
111
|
-
* be removed, and such object state will be labeled as archived.
|
|
112
|
-
*/
|
|
113
|
-
deleteObj(objId: string, archVersion?: number | null): Promise<void>;
|
|
105
|
+
deleteCurrentObjVer(objId: string, version?: number | null): Promise<void>;
|
|
106
|
+
deleteArchivedObjVer(objId: string | null, version: number): Promise<void>;
|
|
114
107
|
/**
|
|
115
108
|
* @param objId is a string object id for non-root objects, and null for
|
|
116
109
|
* root object.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2015 - 2017, 2019 - 2020 3NSoft Inc.
|
|
3
|
+
Copyright (C) 2015 - 2017, 2019 - 2020, 2022 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
|
|
@@ -131,7 +131,7 @@ class Store extends user_files_1.UserFiles {
|
|
|
131
131
|
Object.freeze(this);
|
|
132
132
|
}
|
|
133
133
|
static async make(userFolder, userId, storageEventsSink, writeBufferSize, readBufferSize) {
|
|
134
|
-
const path = path_1.join(userFolder, 'store');
|
|
134
|
+
const path = (0, path_1.join)(userFolder, 'store');
|
|
135
135
|
const store = new Store(userId, path, storageEventsSink, writeBufferSize, readBufferSize);
|
|
136
136
|
await store.ensureUserExistsOnDisk();
|
|
137
137
|
return store;
|
|
@@ -153,7 +153,7 @@ class Store extends user_files_1.UserFiles {
|
|
|
153
153
|
await spaceTracker.change(this, byteLen);
|
|
154
154
|
}
|
|
155
155
|
const params = {
|
|
156
|
-
isNewObj:
|
|
156
|
+
isNewObj: opts.create,
|
|
157
157
|
version: opts.ver,
|
|
158
158
|
baseVersion: (diff ? diff.baseVersion : undefined)
|
|
159
159
|
};
|
|
@@ -163,10 +163,10 @@ class Store extends user_files_1.UserFiles {
|
|
|
163
163
|
const filePath = this.transactions.objFileWritingPath(objId);
|
|
164
164
|
file = await this.objVerFiles.forNewFile(objId, trans.version, filePath);
|
|
165
165
|
if (diff) {
|
|
166
|
-
await file.setSegsLayout(utils_1.diffToLayout(diff), false);
|
|
166
|
+
await file.setSegsLayout((0, utils_1.diffToLayout)(diff), false);
|
|
167
167
|
}
|
|
168
|
-
const chunks = utils_1.chunksInOrderedStream(byteLen, opts.header, 0);
|
|
169
|
-
await utils_1.streamToObjFile(file, chunks, bytes, this.fileWritingBufferSize);
|
|
168
|
+
const chunks = (0, utils_1.chunksInOrderedStream)(byteLen, opts.header, 0);
|
|
169
|
+
await (0, utils_1.streamToObjFile)(file, chunks, bytes, this.fileWritingBufferSize);
|
|
170
170
|
if (opts.last) {
|
|
171
171
|
if (!file.isFileComplete()) {
|
|
172
172
|
throw exports.SC.OBJ_FILE_INCOMPLETE;
|
|
@@ -183,7 +183,7 @@ class Store extends user_files_1.UserFiles {
|
|
|
183
183
|
}
|
|
184
184
|
catch (err) {
|
|
185
185
|
await spaceTracker.change(this, -byteLen);
|
|
186
|
-
await this.transactions.cancel(objId, trans.transactionId).catch(
|
|
186
|
+
await this.transactions.cancel(objId, trans.transactionId).catch(noop);
|
|
187
187
|
throw err;
|
|
188
188
|
}
|
|
189
189
|
}
|
|
@@ -206,8 +206,8 @@ class Store extends user_files_1.UserFiles {
|
|
|
206
206
|
const file = await this.objVerFiles.forExistingFile(objId, trans.version, filePath);
|
|
207
207
|
if (byteLen > 0) {
|
|
208
208
|
await spaceTracker.change(this, byteLen);
|
|
209
|
-
const chunks = utils_1.chunksInOrderedStream(byteLen, undefined, opts.ofs);
|
|
210
|
-
await utils_1.streamToObjFile(file, chunks, bytes, this.fileWritingBufferSize);
|
|
209
|
+
const chunks = (0, utils_1.chunksInOrderedStream)(byteLen, undefined, opts.ofs);
|
|
210
|
+
await (0, utils_1.streamToObjFile)(file, chunks, bytes, this.fileWritingBufferSize);
|
|
211
211
|
}
|
|
212
212
|
if (opts.last) {
|
|
213
213
|
if (!file.isFileComplete()) {
|
|
@@ -302,75 +302,76 @@ class Store extends user_files_1.UserFiles {
|
|
|
302
302
|
len: (segBytesToRead + headerLen),
|
|
303
303
|
segsLen,
|
|
304
304
|
headerLen,
|
|
305
|
-
pipe: utils_1.makeObjPipe(file, true, segsOfs, segBytesToRead, objId, this.getObjFile)
|
|
305
|
+
pipe: (0, utils_1.makeObjPipe)(file, true, segsOfs, segBytesToRead, objId, this.getObjFile)
|
|
306
306
|
};
|
|
307
307
|
}
|
|
308
308
|
else {
|
|
309
309
|
reader = {
|
|
310
310
|
len: segBytesToRead,
|
|
311
311
|
segsLen,
|
|
312
|
-
pipe: utils_1.makeObjPipe(file, false, segsOfs, segBytesToRead, objId, this.getObjFile)
|
|
312
|
+
pipe: (0, utils_1.makeObjPipe)(file, false, segsOfs, segBytesToRead, objId, this.getObjFile)
|
|
313
313
|
};
|
|
314
314
|
}
|
|
315
315
|
Object.freeze(reader);
|
|
316
316
|
return reader;
|
|
317
317
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
* to delete. Default null value indicates that an object should be removed.
|
|
323
|
-
* If an object has any archived versions (even if current), these will not
|
|
324
|
-
* be removed, and such object state will be labeled as archived.
|
|
325
|
-
*/
|
|
326
|
-
async deleteObj(objId, archVersion = null) {
|
|
318
|
+
async deleteCurrentObjVer(objId, version = null) {
|
|
319
|
+
if (!objId) {
|
|
320
|
+
throw new Error('Root object is not removable.');
|
|
321
|
+
}
|
|
327
322
|
const status = await this.statuses.get(objId);
|
|
328
|
-
|
|
323
|
+
if (status.state !== 'current') {
|
|
324
|
+
throw exports.SC.OBJ_UNKNOWN;
|
|
325
|
+
}
|
|
326
|
+
if (version && (version !== status.currentVersion)) {
|
|
327
|
+
throw exports.SC.OBJ_VER_UNKNOWN;
|
|
328
|
+
}
|
|
329
329
|
// XXX need to put removal transaction, closing it in a finally clause
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
if (status.state !== 'current') {
|
|
335
|
-
throw exports.SC.OBJ_UNKNOWN;
|
|
336
|
-
}
|
|
337
|
-
if (!Array.isArray(arch) || (arch.length === 0)) {
|
|
338
|
-
await this.statuses.deleteWithObj(objId);
|
|
339
|
-
}
|
|
340
|
-
else {
|
|
341
|
-
const currVer = status.currentVersion;
|
|
342
|
-
delete status.currentVersion;
|
|
343
|
-
status.state = 'archived';
|
|
344
|
-
await this.statuses.set(objId, status);
|
|
345
|
-
if (typeof currVer !== 'number') {
|
|
346
|
-
throw new Error(`Illegal state of object status file for ${objId}: state is current, while current version is missing.`);
|
|
347
|
-
}
|
|
348
|
-
if (arch.indexOf(currVer) < 0) {
|
|
349
|
-
await this.rmObjFiles(objId, currVer);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
330
|
+
const arch = status.archivedVersions;
|
|
331
|
+
if (!Array.isArray(arch) || (arch.length === 0)) {
|
|
332
|
+
// remove everything related to this object
|
|
333
|
+
await this.statuses.deleteWithObj(objId);
|
|
352
334
|
}
|
|
353
335
|
else {
|
|
354
|
-
if
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
if (indInArch < 0) {
|
|
359
|
-
throw exports.SC.OBJ_UNKNOWN;
|
|
360
|
-
}
|
|
361
|
-
arch.splice(indInArch, 1);
|
|
362
|
-
if (arch.length === 0) {
|
|
363
|
-
delete status.archivedVersions;
|
|
364
|
-
}
|
|
336
|
+
// set status and remove version if it isn't archived
|
|
337
|
+
version = status.currentVersion;
|
|
338
|
+
delete status.currentVersion;
|
|
339
|
+
status.state = 'archived';
|
|
365
340
|
await this.statuses.set(objId, status);
|
|
366
|
-
if (
|
|
367
|
-
await this.rmObjFiles(objId,
|
|
341
|
+
if (arch.indexOf(version) < 0) {
|
|
342
|
+
await this.rmObjFiles(objId, version);
|
|
368
343
|
}
|
|
369
344
|
}
|
|
370
345
|
this.storageEventsSink(this.userId, owner_1.objRemoved.EVENT_NAME, {
|
|
371
346
|
objId,
|
|
372
347
|
});
|
|
373
348
|
}
|
|
349
|
+
async deleteArchivedObjVer(objId, version) {
|
|
350
|
+
const status = await this.statuses.get(objId);
|
|
351
|
+
const arch = status.archivedVersions;
|
|
352
|
+
// XXX need to put removal transaction, closing it in a finally clause
|
|
353
|
+
if (!Array.isArray(arch)) {
|
|
354
|
+
throw exports.SC.OBJ_VER_UNKNOWN;
|
|
355
|
+
}
|
|
356
|
+
const indInArch = arch.indexOf(version);
|
|
357
|
+
if (indInArch < 0) {
|
|
358
|
+
throw exports.SC.OBJ_VER_UNKNOWN;
|
|
359
|
+
}
|
|
360
|
+
arch.splice(indInArch, 1);
|
|
361
|
+
if (arch.length === 0) {
|
|
362
|
+
delete status.archivedVersions;
|
|
363
|
+
}
|
|
364
|
+
await this.statuses.set(objId, status);
|
|
365
|
+
if (!status.archivedVersions && !status.currentVersion) {
|
|
366
|
+
await this.rmObjFiles(objId, version);
|
|
367
|
+
}
|
|
368
|
+
else if (status.currentVersion !== version) {
|
|
369
|
+
await this.statuses.deleteWithObj(objId);
|
|
370
|
+
}
|
|
371
|
+
// this.storageEventsSink(this.userId, objRemoved.EVENT_NAME, {
|
|
372
|
+
// objId,
|
|
373
|
+
// });
|
|
374
|
+
}
|
|
374
375
|
/**
|
|
375
376
|
* @param objId is a string object id for non-root objects, and null for
|
|
376
377
|
* root object.
|
|
@@ -391,10 +392,10 @@ class Store extends user_files_1.UserFiles {
|
|
|
391
392
|
const verPart = toFName(version);
|
|
392
393
|
objFiles = objFiles.filter(fName => fName.startsWith(verPart));
|
|
393
394
|
if (objFiles.length === 0) {
|
|
394
|
-
throw exports.SC.
|
|
395
|
+
throw exports.SC.OBJ_VER_UNKNOWN;
|
|
395
396
|
}
|
|
396
397
|
for (const fName of objFiles) {
|
|
397
|
-
await fs.unlink(path_1.join(objFolder, fName)).catch(() => { });
|
|
398
|
+
await fs.unlink((0, path_1.join)(objFolder, fName)).catch(() => { });
|
|
398
399
|
}
|
|
399
400
|
}
|
|
400
401
|
// XXX need both, archiving and removal transactions for atomic locking
|
|
@@ -404,12 +405,13 @@ class Store extends user_files_1.UserFiles {
|
|
|
404
405
|
// file/folder.
|
|
405
406
|
async archiveCurrentObjVersion(objId, version) {
|
|
406
407
|
// XXX need to put archiving transaction, closing it in a finally clause
|
|
408
|
+
// - make in memory transactions for archival and removal, or chaining(?)
|
|
407
409
|
const status = await this.statuses.get(objId);
|
|
408
410
|
if (status.state !== 'current') {
|
|
409
411
|
throw exports.SC.OBJ_UNKNOWN;
|
|
410
412
|
}
|
|
411
|
-
if (
|
|
412
|
-
throw
|
|
413
|
+
if (status.currentVersion !== version) {
|
|
414
|
+
throw exports.SC.OBJ_VER_UNKNOWN;
|
|
413
415
|
}
|
|
414
416
|
const arch = status.archivedVersions;
|
|
415
417
|
if (Array.isArray(arch)) {
|
|
@@ -501,8 +503,8 @@ class ObjStatuses {
|
|
|
501
503
|
}
|
|
502
504
|
objFolder(objId) {
|
|
503
505
|
return (objId ?
|
|
504
|
-
path_1.join(this.path, 'objects', objId) :
|
|
505
|
-
path_1.join(this.path, 'root'));
|
|
506
|
+
(0, path_1.join)(this.path, 'objects', objId) :
|
|
507
|
+
(0, path_1.join)(this.path, 'root'));
|
|
506
508
|
}
|
|
507
509
|
async get(objId) {
|
|
508
510
|
let status = this.cache.get(objId);
|
|
@@ -513,7 +515,7 @@ class ObjStatuses {
|
|
|
513
515
|
return status;
|
|
514
516
|
}
|
|
515
517
|
async fromFile(objId) {
|
|
516
|
-
const filePath = path_1.join(this.objFolder(objId), STATUS_FILE);
|
|
518
|
+
const filePath = (0, path_1.join)(this.objFolder(objId), STATUS_FILE);
|
|
517
519
|
const str = await fs.readFile(filePath, { encoding: 'utf8', flag: 'r' }).catch((exc) => {
|
|
518
520
|
if (exc.notFound) {
|
|
519
521
|
throw exports.SC.OBJ_UNKNOWN;
|
|
@@ -524,7 +526,7 @@ class ObjStatuses {
|
|
|
524
526
|
return JSON.parse(str);
|
|
525
527
|
}
|
|
526
528
|
catch (err) {
|
|
527
|
-
throw error_1.errWithCause(err, `Can't parse content of obj status file`);
|
|
529
|
+
throw (0, error_1.errWithCause)(err, `Can't parse content of obj status file`);
|
|
528
530
|
}
|
|
529
531
|
}
|
|
530
532
|
async set(objId, status) {
|
|
@@ -532,7 +534,7 @@ class ObjStatuses {
|
|
|
532
534
|
await this.saveToFile(objId, status);
|
|
533
535
|
}
|
|
534
536
|
async saveToFile(objId, status) {
|
|
535
|
-
const filePath = path_1.join(this.objFolder(objId), STATUS_FILE);
|
|
537
|
+
const filePath = (0, path_1.join)(this.objFolder(objId), STATUS_FILE);
|
|
536
538
|
const str = JSON.stringify(status);
|
|
537
539
|
const procId = (objId ? objId : 'null');
|
|
538
540
|
await this.saveProcs.startOrChain(procId, () => fs.writeFile(filePath, str, { encoding: 'utf8', flag: 'w' }));
|
|
@@ -540,7 +542,7 @@ class ObjStatuses {
|
|
|
540
542
|
async deleteWithObj(objId) {
|
|
541
543
|
this.cache.delete(objId);
|
|
542
544
|
if (objId === null) {
|
|
543
|
-
await fs.unlink(path_1.join(this.objFolder(null), STATUS_FILE))
|
|
545
|
+
await fs.unlink((0, path_1.join)(this.objFolder(null), STATUS_FILE))
|
|
544
546
|
.catch(() => { });
|
|
545
547
|
}
|
|
546
548
|
else {
|
|
@@ -571,7 +573,7 @@ class ObjStatuses {
|
|
|
571
573
|
});
|
|
572
574
|
}
|
|
573
575
|
objFileReadingPath(objId, version) {
|
|
574
|
-
return path_1.join(this.objFolder(objId), toFName(version));
|
|
576
|
+
return (0, path_1.join)(this.objFolder(objId), toFName(version));
|
|
575
577
|
}
|
|
576
578
|
}
|
|
577
579
|
Object.freeze(ObjStatuses.prototype);
|
|
@@ -587,8 +589,8 @@ class ObjTransactions {
|
|
|
587
589
|
}
|
|
588
590
|
transactionFolder(objId) {
|
|
589
591
|
return (objId ?
|
|
590
|
-
path_1.join(this.path, 'transactions', objId) :
|
|
591
|
-
path_1.join(this.path, 'root', 'transaction'));
|
|
592
|
+
(0, path_1.join)(this.path, 'transactions', objId) :
|
|
593
|
+
(0, path_1.join)(this.path, 'root', 'transaction'));
|
|
592
594
|
}
|
|
593
595
|
async get(objId, transactionId) {
|
|
594
596
|
let isInCache = true;
|
|
@@ -606,7 +608,7 @@ class ObjTransactions {
|
|
|
606
608
|
return trans;
|
|
607
609
|
}
|
|
608
610
|
transactionFilePath(objId) {
|
|
609
|
-
return path_1.join(this.transactionFolder(objId), 'transaction');
|
|
611
|
+
return (0, path_1.join)(this.transactionFolder(objId), 'transaction');
|
|
610
612
|
}
|
|
611
613
|
async fromFile(objId) {
|
|
612
614
|
const filePath = this.transactionFilePath(objId);
|
|
@@ -625,7 +627,7 @@ class ObjTransactions {
|
|
|
625
627
|
return JSON.parse(str);
|
|
626
628
|
}
|
|
627
629
|
catch (err) {
|
|
628
|
-
throw error_1.errWithCause(err, `Can't parse content of obj transaction file`);
|
|
630
|
+
throw (0, error_1.errWithCause)(err, `Can't parse content of obj transaction file`);
|
|
629
631
|
}
|
|
630
632
|
}
|
|
631
633
|
async set(objId, status) {
|
|
@@ -639,11 +641,11 @@ class ObjTransactions {
|
|
|
639
641
|
await this.saveProcs.startOrChain(procId, () => fs.writeFile(filePath, str, { encoding: 'utf8', flag: 'w' }));
|
|
640
642
|
}
|
|
641
643
|
objFileWritingPath(objId) {
|
|
642
|
-
return path_1.join(this.transactionFolder(objId), 'new');
|
|
644
|
+
return (0, path_1.join)(this.transactionFolder(objId), 'new');
|
|
643
645
|
}
|
|
644
646
|
async startNew(objId, reqTrans) {
|
|
645
647
|
const trans = reqTrans;
|
|
646
|
-
trans.transactionId = await random_node_1.stringOfB64UrlSafeChars(10);
|
|
648
|
+
trans.transactionId = await (0, random_node_1.stringOfB64UrlSafeChars)(10);
|
|
647
649
|
trans.transactionType = 'write';
|
|
648
650
|
await this.makeTransactionFolder(objId);
|
|
649
651
|
await this.set(objId, trans);
|
|
@@ -735,4 +737,5 @@ Object.freeze(ObjStatuses);
|
|
|
735
737
|
function toFName(version) {
|
|
736
738
|
return `${version}.`;
|
|
737
739
|
}
|
|
740
|
+
function noop() { }
|
|
738
741
|
Object.freeze(exports);
|
|
@@ -18,7 +18,8 @@ export declare type GetArchivedObjVersion = (userId: string, objId: string | nul
|
|
|
18
18
|
export declare type CancelTransaction = (userId: string, objId: string, transactionId?: string) => Promise<void>;
|
|
19
19
|
export declare type ArchiveObjCurrentVersion = (userId: string, objId: string, version: number) => Promise<void>;
|
|
20
20
|
export declare type ListObjArchive = (userId: string, objId: string) => Promise<number[]>;
|
|
21
|
-
export declare type
|
|
21
|
+
export declare type DeleteCurrentObjVersion = (userId: string, objId: string, version?: number) => Promise<void>;
|
|
22
|
+
export declare type DeleteArchivedObjVersion = (userId: string, objId: string | null, version: number) => Promise<void>;
|
|
22
23
|
declare type GetParam<T> = (userId: string) => Promise<T>;
|
|
23
24
|
declare type SetParam<T> = (userId: string, param: T) => Promise<boolean>;
|
|
24
25
|
export declare type GetSpaceQuota = GetParam<number>;
|
|
@@ -42,7 +43,8 @@ export interface Factory {
|
|
|
42
43
|
archiveObjVersion: ArchiveObjCurrentVersion;
|
|
43
44
|
getArchivedRootVersion: GetArchivedObjVersion;
|
|
44
45
|
getArchivedObjVersion: GetArchivedObjVersion;
|
|
45
|
-
|
|
46
|
+
deleteCurrentObjVersion: DeleteCurrentObjVersion;
|
|
47
|
+
deleteArchivedObjVersion: DeleteArchivedObjVersion;
|
|
46
48
|
setStorageEventsSink(sink: EventsSink): void;
|
|
47
49
|
}
|
|
48
50
|
export declare function makeFactory(rootFolder: string, writeBufferSize?: string | number, readBufferSize?: string | number): Factory;
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
17
|
*/
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.makeFactory = void 0;
|
|
19
|
+
exports.makeFactory = exports.SC = void 0;
|
|
20
20
|
const store_1 = require("./store");
|
|
21
21
|
const server_data_folders_1 = require("../../lib-server/resources/server-data-folders");
|
|
22
22
|
var store_2 = require("./store");
|
|
@@ -40,7 +40,7 @@ function makeFactory(rootFolder, writeBufferSize, readBufferSize) {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
else {
|
|
43
|
-
const userFolder = server_data_folders_1.userDataInRootFolder(rootFolder, userId);
|
|
43
|
+
const userFolder = (0, server_data_folders_1.userDataInRootFolder)(rootFolder, userId);
|
|
44
44
|
const store = await store_1.Store.make(userFolder, userId, storageEventsSink, writeBufferSize, readBufferSize);
|
|
45
45
|
stores.set(userId, store);
|
|
46
46
|
return store;
|
|
@@ -122,9 +122,9 @@ function makeFactory(rootFolder, writeBufferSize, readBufferSize) {
|
|
|
122
122
|
saveNewRootVersion: makeObjSaver(true),
|
|
123
123
|
saveNewObjVersion: makeObjSaver(false),
|
|
124
124
|
cancelTransaction: makeTransactionCanceller(),
|
|
125
|
-
|
|
125
|
+
deleteCurrentObjVersion: async (userId, objId, version) => {
|
|
126
126
|
const store = await getStore(userId);
|
|
127
|
-
await store.
|
|
127
|
+
await store.deleteCurrentObjVer(objId, version);
|
|
128
128
|
},
|
|
129
129
|
archiveObjVersion: async (userId, objId, version) => {
|
|
130
130
|
const store = await getStore(userId);
|
|
@@ -134,6 +134,10 @@ function makeFactory(rootFolder, writeBufferSize, readBufferSize) {
|
|
|
134
134
|
const store = await getStore(userId);
|
|
135
135
|
return store.listObjArchive(objId);
|
|
136
136
|
},
|
|
137
|
+
deleteArchivedObjVersion: async (userId, objId, version) => {
|
|
138
|
+
const store = await getStore(userId);
|
|
139
|
+
await store.deleteArchivedObjVer(objId, version);
|
|
140
|
+
},
|
|
137
141
|
setStorageEventsSink(sink) {
|
|
138
142
|
if (storageEventsSink) {
|
|
139
143
|
throw new Error(`Storage events sink is already set`);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { RequestHandler } from 'express';
|
|
2
2
|
import { ArchiveObjCurrentVersion } from '../../resources/users';
|
|
3
|
-
export declare function archiveCurrentObjVersion(root: boolean, archiveObjVerFunc: ArchiveObjCurrentVersion):
|
|
3
|
+
export declare function archiveCurrentObjVersion(root: boolean, archiveObjVerFunc: ArchiveObjCurrentVersion): RequestHandler;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C)
|
|
3
|
+
Copyright (C) 2022 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
|
|
@@ -13,44 +13,49 @@
|
|
|
13
13
|
See the GNU General Public License for more details.
|
|
14
14
|
|
|
15
15
|
You should have received a copy of the GNU General Public License along with
|
|
16
|
-
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
*/
|
|
17
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
19
|
exports.archiveCurrentObjVersion = void 0;
|
|
20
|
+
const users_1 = require("../../resources/users");
|
|
19
21
|
const owner_1 = require("../../../lib-common/service-api/3nstorage/owner");
|
|
20
22
|
const SC = owner_1.archiveObj.SC;
|
|
21
23
|
function archiveCurrentObjVersion(root, archiveObjVerFunc) {
|
|
22
24
|
if ('function' !== typeof archiveObjVerFunc) {
|
|
23
25
|
throw new TypeError("Given argument 'archiveObjVerFunc' must be function, but is not.");
|
|
24
26
|
}
|
|
25
|
-
return async
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
27
|
+
return async (req, res, next) => {
|
|
28
|
+
const userId = req.session.params.userId;
|
|
29
|
+
const objId = (root ? null : req.params.objId);
|
|
30
|
+
const version = parseInt(req.query.ver);
|
|
31
|
+
if (isNaN(version) || (version < 1)) {
|
|
32
|
+
res.status(owner_1.ERR_SC.malformed).send("Bad query parameters");
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
await archiveObjVerFunc(userId, objId, version);
|
|
37
|
+
res.status(SC.okPost).end();
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
if ("string" !== typeof err) {
|
|
41
|
+
next(err);
|
|
42
|
+
}
|
|
43
|
+
else if (err === users_1.SC.OBJ_VER_UNKNOWN) {
|
|
44
|
+
res.status(SC.unknownObjVer).send(`Object ${objId} version ${version} is not current.`);
|
|
45
|
+
}
|
|
46
|
+
else if (err === users_1.SC.OBJ_UNKNOWN) {
|
|
47
|
+
res.status(SC.unknownObj).send(root ?
|
|
48
|
+
`Root object is not set.` :
|
|
49
|
+
`Object ${objId} is unknown.`);
|
|
50
|
+
}
|
|
51
|
+
else if (err === users_1.SC.USER_UNKNOWN) {
|
|
52
|
+
res.status(owner_1.ERR_SC.server).send("Recipient disappeared from the system.");
|
|
53
|
+
req.session.close();
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
next(new Error("Unhandled storage error code: " + err));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
54
59
|
};
|
|
55
60
|
}
|
|
56
61
|
exports.archiveCurrentObjVersion = archiveCurrentObjVersion;
|
|
@@ -23,7 +23,7 @@ function cancelTransaction(root, cancelTransFunc) {
|
|
|
23
23
|
if ('function' !== typeof cancelTransFunc) {
|
|
24
24
|
throw new TypeError("Given argument 'cancelTransFunc' must be function, but is not.");
|
|
25
25
|
}
|
|
26
|
-
return async
|
|
26
|
+
return async (req, res, next) => {
|
|
27
27
|
const userId = req.session.params.userId;
|
|
28
28
|
const objId = (root ? null : req.params.objId);
|
|
29
29
|
const transactionId = req.params.transactionId;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { RequestHandler } from 'express';
|
|
2
|
-
import {
|
|
3
|
-
export declare function
|
|
2
|
+
import { DeleteArchivedObjVersion, DeleteCurrentObjVersion } from '../../resources/users';
|
|
3
|
+
export declare function deleteCurrentObjVer(deleteObjFunc: DeleteCurrentObjVersion): RequestHandler;
|
|
4
|
+
export declare function deleteArchivedObjVer(root: boolean, deleteObjFunc: DeleteArchivedObjVersion): RequestHandler;
|