spec-3nweb-server 1.4.1 → 1.5.2

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.
@@ -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
@@ -48,8 +48,7 @@ function makeApp(domain, sessions, users, midAuthorizer) {
48
48
  exports.makeApp = makeApp;
49
49
  function setWSPart(app, sessions, users) {
50
50
  const sockets = new app_1.UserSockets(sessions.ensureAuthorizedSessionForSocketStart());
51
- const storageEvents = new server_events_1.ServerEvents(undefined, [api.objChanged.EVENT_NAME,
52
- api.objRemoved.EVENT_NAME], sockets.socketGetter);
51
+ const storageEvents = new server_events_1.ServerEvents(undefined, api.events.all, sockets.socketGetter);
53
52
  // give events ipc to both ends
54
53
  sockets.addSocketIPC(storageEvents);
55
54
  users.setStorageEventsSink(storageEvents.eventsSink);
@@ -73,30 +72,30 @@ function setHttpPart(app, domain, sessions, users, midAuthorizer) {
73
72
  // Transaction canceling
74
73
  app.http.post('/' + api.cancelTransaction.EXPRESS_URL_END, (0, body_parsers_1.emptyBody)(), (0, cancel_trans_1.cancelTransaction)(false, users.cancelTransaction));
75
74
  app.http.post('/' + api.cancelRootTransaction.EXPRESS_URL_END, (0, body_parsers_1.emptyBody)(), (0, cancel_trans_1.cancelTransaction)(true, users.cancelTransaction));
76
- // Getting current root object
75
+ // Getting and updating current root object
77
76
  app.http.route('/' + api.currentRootObj.EXPRESS_URL_END)
78
77
  .get((0, get_current_obj_1.getCurrentObj)(true, users.getCurrentRootObj))
79
78
  .put((0, put_current_obj_1.saveCurrentObj)(true, users.saveNewRootVersion, MAX_CHUNK_SIZE));
80
- // Getting current non-root objects
79
+ // Getting, updating and removing current non-root objects
81
80
  app.http.route('/' + api.currentObj.EXPRESS_URL_END)
82
81
  .get((0, get_current_obj_1.getCurrentObj)(false, users.getCurrentObj))
83
- .delete((0, delete_obj_1.deleteObj)(false, true, users.deleteObj))
82
+ .delete((0, delete_obj_1.deleteCurrentObjVer)(users.deleteCurrentObjVersion))
84
83
  .put((0, put_current_obj_1.saveCurrentObj)(false, users.saveNewObjVersion, MAX_CHUNK_SIZE));
84
+ // Getting root archived versions
85
+ app.http.route('/' + api.archivedRootVersion.EXPRESS_URL_END)
86
+ .get((0, get_archived_obj_ver_1.getArchivedObjVersion)(true, users.getArchivedRootVersion));
87
+ // Getting non-root object archived versions
88
+ app.http.route('/' + api.archivedObjVersion.EXPRESS_URL_END)
89
+ .get((0, get_archived_obj_ver_1.getArchivedObjVersion)(false, users.getArchivedObjVersion));
85
90
  // Archive root's current version
86
91
  app.http.route('/' + api.archiveRoot.URL_END)
87
92
  .get((0, list_obj_archive_1.listObjArchive)(true, users.listObjArchive))
88
- .put((0, body_parsers_1.emptyBody)(), (0, archive_obj_version_1.archiveCurrentObjVersion)(true, users.archiveObjVersion));
93
+ .post((0, body_parsers_1.emptyBody)(), (0, archive_obj_version_1.archiveCurrentObjVersion)(true, users.archiveObjVersion))
94
+ .delete((0, delete_obj_1.deleteArchivedObjVer)(true, users.deleteArchivedObjVersion));
89
95
  // Archive non-root object's current version
90
96
  app.http.route('/' + api.archiveObj.EXPRESS_URL_END)
91
97
  .get((0, list_obj_archive_1.listObjArchive)(false, users.listObjArchive))
92
- .put((0, body_parsers_1.emptyBody)(), (0, archive_obj_version_1.archiveCurrentObjVersion)(false, users.archiveObjVersion));
93
- // Archived root versions
94
- app.http.route('/' + api.archivedRootVersion.EXPRESS_URL_END)
95
- .get((0, get_archived_obj_ver_1.getArchivedObjVersion)(true, users.getArchivedRootVersion))
96
- .delete((0, 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((0, get_archived_obj_ver_1.getArchivedObjVersion)(true, users.getArchivedObjVersion))
100
- .delete((0, delete_obj_1.deleteObj)(false, false, users.deleteObj));
98
+ .post((0, body_parsers_1.emptyBody)(), (0, archive_obj_version_1.archiveCurrentObjVersion)(false, users.archiveObjVersion))
99
+ .delete((0, delete_obj_1.deleteArchivedObjVer)(false, users.deleteArchivedObjVersion));
101
100
  }
102
101
  Object.freeze(exports);
@@ -2,11 +2,10 @@
2
2
  import { Readable } from 'stream';
3
3
  import { PutObjFirstQueryOpts, PutObjSecondQueryOpts } from '../../lib-common/service-api/3nstorage/owner';
4
4
  import { UserFiles, ObjReader } from '../../lib-server/resources/user-files';
5
- import { DiffInfo, objChanged, objRemoved } from '../../lib-common/service-api/3nstorage/owner';
5
+ import { DiffInfo, events } from '../../lib-common/service-api/3nstorage/owner';
6
6
  export { DiffInfo } from '../../lib-common/service-api/3nstorage/owner';
7
7
  export { ObjPipe, ObjReader } from '../../lib-server/resources/user-files';
8
- export declare type MsgEvents = objChanged.Event | objRemoved.Event;
9
- export declare type StorageEventsSink = (userId: string, channel: string, event: MsgEvents) => void;
8
+ export declare type StorageEventsSink = (userId: string, channel: events.EventNameType, event: events.AllTypes) => void;
10
9
  export declare const SC: {
11
10
  USER_UNKNOWN: string;
12
11
  OBJ_EXIST: string;
@@ -102,15 +101,8 @@ export declare class Store extends UserFiles {
102
101
  getArchivedObjVersion(objId: string | null, version: number, header: boolean, segsOffset: number, segsLimit: number | undefined): Promise<ObjReader>;
103
102
  private makeObjReader;
104
103
  private getObjFile;
105
- /**
106
- * @param objId is a string object id for non-root objects, and null for
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>;
104
+ deleteCurrentObjVer(objId: string, version?: number | null): Promise<void>;
105
+ deleteArchivedObjVer(objId: string | null, version: number): Promise<void>;
114
106
  /**
115
107
  * @param objId is a string object id for non-root objects, and null for
116
108
  * 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
@@ -172,10 +172,7 @@ class Store extends user_files_1.UserFiles {
172
172
  throw exports.SC.OBJ_FILE_INCOMPLETE;
173
173
  }
174
174
  await this.transactions.complete(objId, trans, file);
175
- this.storageEventsSink(this.userId, owner_1.objChanged.EVENT_NAME, {
176
- objId,
177
- newVer: opts.ver
178
- });
175
+ this.storageEventsSink(this.userId, owner_1.events.objChanged.EVENT_NAME, { objId, newVer: opts.ver });
179
176
  }
180
177
  else {
181
178
  return trans.transactionId;
@@ -214,10 +211,7 @@ class Store extends user_files_1.UserFiles {
214
211
  throw exports.SC.OBJ_FILE_INCOMPLETE;
215
212
  }
216
213
  await this.transactions.complete(objId, trans, file);
217
- this.storageEventsSink(this.userId, owner_1.objChanged.EVENT_NAME, {
218
- objId,
219
- newVer: trans.version
220
- });
214
+ this.storageEventsSink(this.userId, owner_1.events.objChanged.EVENT_NAME, { objId, newVer: trans.version });
221
215
  }
222
216
  else {
223
217
  return opts.trans;
@@ -315,61 +309,58 @@ class Store extends user_files_1.UserFiles {
315
309
  Object.freeze(reader);
316
310
  return reader;
317
311
  }
318
- /**
319
- * @param objId is a string object id for non-root objects, and null for
320
- * root object.
321
- * @param archVersion is an optional parameter, identifying archived version
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) {
312
+ async deleteCurrentObjVer(objId, version = null) {
313
+ if (!objId) {
314
+ throw new Error('Root object is not removable.');
315
+ }
327
316
  const status = await this.statuses.get(objId);
328
- const arch = status.archivedVersions;
317
+ if (status.state !== 'current') {
318
+ throw exports.SC.OBJ_UNKNOWN;
319
+ }
320
+ if (version && (version !== status.currentVersion)) {
321
+ throw exports.SC.OBJ_VER_UNKNOWN;
322
+ }
329
323
  // XXX need to put removal transaction, closing it in a finally clause
330
- if (archVersion === null) {
331
- if (objId === null) {
332
- throw new Error('Root object is not removable.');
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
- }
324
+ const arch = status.archivedVersions;
325
+ if (!Array.isArray(arch) || (arch.length === 0)) {
326
+ // remove everything related to this object
327
+ await this.statuses.deleteWithObj(objId);
352
328
  }
353
329
  else {
354
- if (!Array.isArray(arch)) {
355
- throw exports.SC.OBJ_UNKNOWN;
356
- }
357
- const indInArch = arch.indexOf(archVersion);
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
- }
330
+ // set status and remove version if it isn't archived
331
+ version = status.currentVersion;
332
+ delete status.currentVersion;
333
+ status.state = 'archived';
365
334
  await this.statuses.set(objId, status);
366
- if (status.currentVersion !== archVersion) {
367
- await this.rmObjFiles(objId, archVersion);
335
+ if (arch.indexOf(version) < 0) {
336
+ await this.rmObjFiles(objId, version);
368
337
  }
369
338
  }
370
- this.storageEventsSink(this.userId, owner_1.objRemoved.EVENT_NAME, {
371
- objId,
372
- });
339
+ this.storageEventsSink(this.userId, owner_1.events.objRemoved.EVENT_NAME, { objId });
340
+ }
341
+ async deleteArchivedObjVer(objId, version) {
342
+ const status = await this.statuses.get(objId);
343
+ const arch = status.archivedVersions;
344
+ // XXX need to put removal transaction, closing it in a finally clause
345
+ if (!Array.isArray(arch)) {
346
+ throw exports.SC.OBJ_VER_UNKNOWN;
347
+ }
348
+ const indInArch = arch.indexOf(version);
349
+ if (indInArch < 0) {
350
+ throw exports.SC.OBJ_VER_UNKNOWN;
351
+ }
352
+ arch.splice(indInArch, 1);
353
+ if (arch.length === 0) {
354
+ delete status.archivedVersions;
355
+ }
356
+ await this.statuses.set(objId, status);
357
+ if (!status.archivedVersions && !status.currentVersion) {
358
+ await this.rmObjFiles(objId, version);
359
+ }
360
+ else if (status.currentVersion !== version) {
361
+ await this.statuses.deleteWithObj(objId);
362
+ }
363
+ this.storageEventsSink(this.userId, owner_1.events.objArchivedVersionRemoved.EVENT_NAME, { objId, archivedVer: version });
373
364
  }
374
365
  /**
375
366
  * @param objId is a string object id for non-root objects, and null for
@@ -391,7 +382,7 @@ class Store extends user_files_1.UserFiles {
391
382
  const verPart = toFName(version);
392
383
  objFiles = objFiles.filter(fName => fName.startsWith(verPart));
393
384
  if (objFiles.length === 0) {
394
- throw exports.SC.OBJ_UNKNOWN;
385
+ throw exports.SC.OBJ_VER_UNKNOWN;
395
386
  }
396
387
  for (const fName of objFiles) {
397
388
  await fs.unlink((0, path_1.join)(objFolder, fName)).catch(() => { });
@@ -404,12 +395,13 @@ class Store extends user_files_1.UserFiles {
404
395
  // file/folder.
405
396
  async archiveCurrentObjVersion(objId, version) {
406
397
  // XXX need to put archiving transaction, closing it in a finally clause
398
+ // - make in memory transactions for archival and removal, or chaining(?)
407
399
  const status = await this.statuses.get(objId);
408
400
  if (status.state !== 'current') {
409
401
  throw exports.SC.OBJ_UNKNOWN;
410
402
  }
411
- if (typeof status.currentVersion !== 'number') {
412
- throw new Error(`Illegal state of object status file for ${objId}: state is current, while current version is missing.`);
403
+ if (status.currentVersion !== version) {
404
+ throw exports.SC.OBJ_VER_UNKNOWN;
413
405
  }
414
406
  const arch = status.archivedVersions;
415
407
  if (Array.isArray(arch)) {
@@ -419,6 +411,7 @@ class Store extends user_files_1.UserFiles {
419
411
  status.archivedVersions = [status.currentVersion];
420
412
  }
421
413
  await this.statuses.set(objId, status);
414
+ this.storageEventsSink(this.userId, owner_1.events.objVersionArchived.EVENT_NAME, { objId, archivedVer: version });
422
415
  }
423
416
  async listObjArchive(objId) {
424
417
  const status = await this.statuses.get(objId);
@@ -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 DeleteObj = (userId: string, objId: string, version: number) => Promise<void>;
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
- deleteObj: DeleteObj;
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;
@@ -122,9 +122,9 @@ function makeFactory(rootFolder, writeBufferSize, readBufferSize) {
122
122
  saveNewRootVersion: makeObjSaver(true),
123
123
  saveNewObjVersion: makeObjSaver(false),
124
124
  cancelTransaction: makeTransactionCanceller(),
125
- deleteObj: async (userId, objId, version) => {
125
+ deleteCurrentObjVersion: async (userId, objId, version) => {
126
126
  const store = await getStore(userId);
127
- await store.deleteObj(objId, version);
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,6 +1,6 @@
1
1
  "use strict";
2
2
  /*
3
- Copyright (C) 2016 3NSoft Inc.
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
@@ -17,6 +17,7 @@
17
17
  */
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
19
  exports.archiveCurrentObjVersion = void 0;
20
+ const users_1 = require("../../resources/users");
20
21
  const owner_1 = require("../../../lib-common/service-api/3nstorage/owner");
21
22
  const SC = owner_1.archiveObj.SC;
22
23
  function archiveCurrentObjVersion(root, archiveObjVerFunc) {
@@ -24,34 +25,37 @@ function archiveCurrentObjVersion(root, archiveObjVerFunc) {
24
25
  throw new TypeError("Given argument 'archiveObjVerFunc' must be function, but is not.");
25
26
  }
26
27
  return async (req, res, next) => {
27
- next(new Error('Not implemented, yet.'));
28
- // const userId = req.session.params.userId;
29
- // const objId: string = (root ? null : req.params.objId);
30
- // const version: number = (delCurrent ? null : req.params.version);
31
- // try {
32
- // await deleteObjFunc(userId, objId, version);
33
- // res.status(SC.ok).end();
34
- // } catch (err) {
35
- // if ("string" !== typeof err) {
36
- // next(err);
37
- // } else if (err === storeSC.CONCURRENT_TRANSACTION) {
38
- // res.status(SC.concurrentTransaction).send(
39
- // `Object ${objId} is currently under a transaction.`);
40
- // } else if (err === storeSC.OBJ_UNKNOWN) {
41
- // res.status(SC.unknownObj).send((version === null) ?
42
- // `Object ${objId} is unknown.` :
43
- // `Object ${objId} version ${version} is unknown.`);
44
- // } else if (err === storeSC.WRONG_OBJ_STATE) {
45
- // res.status(SC.incompatibleObjState).send(
46
- // `Object ${objId} is in a state, that does not allow to procede with this request.`);
47
- // } else if (err === storeSC.USER_UNKNOWN) {
48
- // res.status(api.ERR_SC.server).send(
49
- // "Recipient disappeared from the system.");
50
- // req.session.close();
51
- // } else {
52
- // next(new Error("Unhandled storage error code: "+err));
53
- // }
54
- // }
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
+ }
55
59
  };
56
60
  }
57
61
  exports.archiveCurrentObjVersion = archiveCurrentObjVersion;
@@ -1,3 +1,4 @@
1
1
  import { RequestHandler } from 'express';
2
- import { DeleteObj } from '../../resources/users';
3
- export declare function deleteObj(root: boolean, delCurrent: boolean, deleteObjFunc: DeleteObj): RequestHandler;
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;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /*
3
- Copyright (C) 2016, 2020 3NSoft Inc.
3
+ Copyright (C) 2016, 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
@@ -16,19 +16,45 @@
16
16
  this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
- exports.deleteObj = void 0;
19
+ exports.deleteArchivedObjVer = exports.deleteCurrentObjVer = void 0;
20
20
  const users_1 = require("../../resources/users");
21
21
  const owner_1 = require("../../../lib-common/service-api/3nstorage/owner");
22
+ const assert_1 = require("../../../lib-common/assert");
22
23
  function deleteObj(root, delCurrent, deleteObjFunc) {
23
24
  if ('function' !== typeof deleteObjFunc) {
24
25
  throw new TypeError("Given argument 'deleteObjFunc' must be function, but is not.");
25
26
  }
27
+ if (delCurrent) {
28
+ (0, assert_1.assert)(!root);
29
+ }
26
30
  return async (req, res, next) => {
27
31
  const userId = req.session.params.userId;
28
32
  const objId = (root ? null : req.params.objId);
29
- const version = (delCurrent ? null : req.params.version);
33
+ const ver = parseInt(req.query.ver);
34
+ let version;
35
+ if (isNaN(ver)) {
36
+ if (delCurrent) {
37
+ version = undefined;
38
+ }
39
+ else {
40
+ res.status(owner_1.ERR_SC.malformed).send("Bad query parameters");
41
+ return;
42
+ }
43
+ }
44
+ else {
45
+ if (ver < 1) {
46
+ res.status(owner_1.ERR_SC.malformed).send("Bad query parameters");
47
+ return;
48
+ }
49
+ version = ver;
50
+ }
30
51
  try {
31
- await deleteObjFunc(userId, objId, version);
52
+ if (delCurrent) {
53
+ await deleteObjFunc(userId, objId, version);
54
+ }
55
+ else {
56
+ await deleteObjFunc(userId, objId, version);
57
+ }
32
58
  res.status(owner_1.currentObj.SC.okDelete).end();
33
59
  }
34
60
  catch (err) {
@@ -41,6 +67,9 @@ function deleteObj(root, delCurrent, deleteObjFunc) {
41
67
  else if (err === users_1.SC.OBJ_UNKNOWN) {
42
68
  res.status(owner_1.currentObj.SC.unknownObj).send(`Object ${objId} is unknown.`);
43
69
  }
70
+ else if (err === users_1.SC.OBJ_VER_UNKNOWN) {
71
+ res.status(owner_1.currentObj.SC.unknownObjVer).send(`Object version ${version} is unknown.`);
72
+ }
44
73
  else if (err === users_1.SC.USER_UNKNOWN) {
45
74
  res.status(owner_1.ERR_SC.server).send("Recipient disappeared from the system.");
46
75
  req.session.close();
@@ -51,6 +80,12 @@ function deleteObj(root, delCurrent, deleteObjFunc) {
51
80
  }
52
81
  };
53
82
  }
54
- exports.deleteObj = deleteObj;
55
- ;
83
+ function deleteCurrentObjVer(deleteObjFunc) {
84
+ return deleteObj(false, true, deleteObjFunc);
85
+ }
86
+ exports.deleteCurrentObjVer = deleteCurrentObjVer;
87
+ function deleteArchivedObjVer(root, deleteObjFunc) {
88
+ return deleteObj(root, false, deleteObjFunc);
89
+ }
90
+ exports.deleteArchivedObjVer = deleteArchivedObjVer;
56
91
  Object.freeze(exports);
@@ -85,10 +85,14 @@ function getArchivedObjVersion(root, getArchivedObjFunc) {
85
85
  if ("string" !== typeof err) {
86
86
  next(err);
87
87
  }
88
- else if ((err === users_1.SC.OBJ_UNKNOWN)
89
- || (err === users_1.SC.OBJ_VER_UNKNOWN)) {
90
- res.status(owner_1.archivedObjVersion.SC.missing).send(objId ?
91
- `Object ${objId}, version ${opts.ver} is unknown.` : `Root object version ${opts.ver} is not known.`);
88
+ else if (err === users_1.SC.OBJ_UNKNOWN) {
89
+ res.status(owner_1.archivedObjVersion.SC.unknownObj).send(objId ?
90
+ `Object ${objId}is unknown.` : `Root object is not set`);
91
+ }
92
+ else if (err === users_1.SC.OBJ_VER_UNKNOWN) {
93
+ res.status(owner_1.archivedObjVersion.SC.unknownObjVer).send(objId ?
94
+ `Object ${objId}, version ${opts.ver} is unknown.` :
95
+ `Root object version ${opts.ver} is not known.`);
92
96
  }
93
97
  else if (err === users_1.SC.USER_UNKNOWN) {
94
98
  res.status(owner_1.ERR_SC.server).send(`Recipient disappeared from the system.`);
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /*
3
- Copyright (C) 2016 3NSoft Inc.
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
@@ -17,39 +17,35 @@
17
17
  */
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
19
  exports.listObjArchive = void 0;
20
+ const users_1 = require("../../resources/users");
21
+ const owner_1 = require("../../../lib-common/service-api/3nstorage/owner");
20
22
  function listObjArchive(root, listObjArchiveFunc) {
21
23
  if ('function' !== typeof listObjArchiveFunc) {
22
24
  throw new TypeError("Given argument 'listObjArchiveFunc' must be function, but is not.");
23
25
  }
24
26
  return async (req, res, next) => {
25
- next(new Error('Not implemented, yet.'));
26
- // const userId = req.session.params.userId;
27
- // const objId: string = (root ? null : req.params.objId);
28
- // const version: number = (delCurrent ? null : req.params.version);
29
- // try {
30
- // await deleteObjFunc(userId, objId, version);
31
- // res.status(SC.ok).end();
32
- // } catch (err) {
33
- // if ("string" !== typeof err) {
34
- // next(err);
35
- // } else if (err === storeSC.CONCURRENT_TRANSACTION) {
36
- // res.status(SC.concurrentTransaction).send(
37
- // `Object ${objId} is currently under a transaction.`);
38
- // } else if (err === storeSC.OBJ_UNKNOWN) {
39
- // res.status(SC.unknownObj).send((version === null) ?
40
- // `Object ${objId} is unknown.` :
41
- // `Object ${objId} version ${version} is unknown.`);
42
- // } else if (err === storeSC.WRONG_OBJ_STATE) {
43
- // res.status(SC.incompatibleObjState).send(
44
- // `Object ${objId} is in a state, that does not allow to procede with this request.`);
45
- // } else if (err === storeSC.USER_UNKNOWN) {
46
- // res.status(api.ERR_SC.server).send(
47
- // "Recipient disappeared from the system.");
48
- // req.session.close();
49
- // } else {
50
- // next(new Error("Unhandled storage error code: "+err));
51
- // }
52
- // }
27
+ const userId = req.session.params.userId;
28
+ const objId = (root ? null : req.params.objId);
29
+ try {
30
+ const lst = await listObjArchiveFunc(userId, objId);
31
+ res.status(owner_1.archiveObj.SC.okGet).json(lst);
32
+ }
33
+ catch (err) {
34
+ if ("string" !== typeof err) {
35
+ next(err);
36
+ }
37
+ else if (err === users_1.SC.OBJ_UNKNOWN) {
38
+ res.status(owner_1.archiveObj.SC.unknownObj).send(root ?
39
+ `Root object is set.` : `Object ${objId} is unknown.`);
40
+ }
41
+ else if (err === users_1.SC.USER_UNKNOWN) {
42
+ res.status(owner_1.ERR_SC.server).send("Recipient disappeared from the system.");
43
+ req.session.close();
44
+ }
45
+ else {
46
+ next(new Error("Unhandled storage error code: " + err));
47
+ }
48
+ }
53
49
  };
54
50
  }
55
51
  exports.listObjArchive = listObjArchive;
@@ -1,4 +1,6 @@
1
1
  /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ /// <reference types="node" />
2
4
  import * as fs from 'fs';
3
5
  import { Readable, Writable } from 'stream';
4
6
  export { Stats } from 'fs';
@@ -1,4 +1,5 @@
1
1
  /// <reference types="node" />
2
+ /// <reference types="node" />
2
3
  import { Layout } from 'xsp-files';
3
4
  import { DiffInfo } from '../service-api/3nstorage/owner';
4
5
  import { ObjVersionFile } from './obj-file';
@@ -157,24 +157,20 @@ export declare namespace currentRootObj {
157
157
  }
158
158
  export declare namespace archivedObjVersion {
159
159
  const EXPRESS_URL_END = "/obj/:objId/archived";
160
- function getReqUrlEnd(objId: string, version: number, opts?: GetObjQueryOpts): string;
160
+ function getReqUrlEnd(objId: string, opts: GetObjQueryOpts): string;
161
161
  const SC: {
162
162
  okGet: number;
163
- okDelete: number;
164
- missing: number;
165
- concurrentTransaction: number;
166
- incompatibleObjState: number;
163
+ unknownObj: number;
164
+ unknownObjVer: number;
167
165
  };
168
166
  }
169
167
  export declare namespace archivedRootVersion {
170
168
  const EXPRESS_URL_END = "root/archived";
171
- function getReqUrlEnd(version: number, opts?: GetObjQueryOpts): string;
169
+ function getReqUrlEnd(opts: GetObjQueryOpts): string;
172
170
  const SC: {
173
171
  okGet: number;
174
- okDelete: number;
175
- missing: number;
176
- concurrentTransaction: number;
177
- incompatibleObjState: number;
172
+ unknownObj: number;
173
+ unknownObjVer: number;
178
174
  };
179
175
  }
180
176
  export interface DiffInfo {
@@ -221,18 +217,27 @@ export declare namespace cancelRootTransaction {
221
217
  export declare namespace archiveObj {
222
218
  const EXPRESS_URL_END = "obj/:objId/archive";
223
219
  function getReqUrlEnd(objId: string): string;
220
+ function postAndDelReqUrlEnd(objId: string, version: number): string;
221
+ type VersionsList = number[];
224
222
  const SC: {
225
223
  okGet: number;
226
- okPut: number;
227
- missing: number;
224
+ okPost: number;
225
+ okDelete: number;
226
+ unknownObj: number;
227
+ unknownObjVer: number;
228
228
  };
229
229
  }
230
230
  export declare namespace archiveRoot {
231
231
  const URL_END = "root/archive";
232
+ function getReqUrlEnd(): string;
233
+ function postAndDelReqUrlEnd(version: number): string;
234
+ type VersionsList = archiveObj.VersionsList;
232
235
  const SC: {
233
236
  okGet: number;
234
- okPut: number;
235
- missing: number;
237
+ okPost: number;
238
+ okDelete: number;
239
+ unknownObj: number;
240
+ unknownObjVer: number;
236
241
  };
237
242
  }
238
243
  export interface ErrorReply {
@@ -244,23 +249,59 @@ export declare namespace wsEventChannel {
244
249
  ok: number;
245
250
  };
246
251
  }
247
- export declare namespace objChanged {
248
- const EVENT_NAME = "obj-changed";
249
- interface Event {
250
- /**
251
- * This indentifies a non-root object by its string id, while null value
252
- * identifies root object.
253
- */
254
- objId: string | null;
255
- newVer: number;
252
+ export declare namespace events {
253
+ namespace objChanged {
254
+ const EVENT_NAME = "obj-changed";
255
+ interface Event {
256
+ /**
257
+ * This indentifies a non-root object by its string id, while null
258
+ * value identifies root object.
259
+ */
260
+ objId: string | null;
261
+ /**
262
+ * New current version on the server.
263
+ */
264
+ newVer: number;
265
+ }
256
266
  }
257
- }
258
- export declare namespace objRemoved {
259
- const EVENT_NAME = "obj-removed";
260
- interface Event {
261
- /**
262
- * This indentifies a removed non-root object by its string id.
263
- */
264
- objId: string;
267
+ namespace objRemoved {
268
+ const EVENT_NAME = "obj-removed";
269
+ interface Event {
270
+ /**
271
+ * This indentifies a removed non-root object by its string id.
272
+ */
273
+ objId: string;
274
+ }
275
+ }
276
+ namespace objVersionArchived {
277
+ const EVENT_NAME = "obj-ver-archived";
278
+ interface Event {
279
+ /**
280
+ * This indentifies a non-root object by its string id, while null
281
+ * value identifies root object.
282
+ */
283
+ objId: string | null;
284
+ /**
285
+ * Version that was set archived on the server.
286
+ */
287
+ archivedVer: number;
288
+ }
289
+ }
290
+ namespace objArchivedVersionRemoved {
291
+ const EVENT_NAME = "obj-ver-removed";
292
+ interface Event {
293
+ /**
294
+ * This indentifies a non-root object by its string id, while null
295
+ * value identifies root object.
296
+ */
297
+ objId: string | null;
298
+ /**
299
+ * Archived version that was removed on the server.
300
+ */
301
+ archivedVer: number;
302
+ }
265
303
  }
304
+ const all: string[];
305
+ type EventNameType = (typeof objChanged.EVENT_NAME) | (typeof objRemoved.EVENT_NAME) | (typeof objVersionArchived.EVENT_NAME) | (typeof objArchivedVersionRemoved.EVENT_NAME);
306
+ type AllTypes = objChanged.Event | objRemoved.Event | objVersionArchived.Event | objArchivedVersionRemoved.Event;
266
307
  }
@@ -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.objRemoved = exports.objChanged = exports.wsEventChannel = exports.archiveRoot = exports.archiveObj = exports.cancelRootTransaction = exports.cancelTransaction = exports.addDiffSectionTo = exports.sanitizedDiff = exports.archivedRootVersion = exports.archivedObjVersion = exports.currentRootObj = exports.currentObj = exports.keyDerivParams = exports.PARAM_SC = exports.sessionParams = exports.closeSession = exports.midLogin = exports.BIN_TYPE = exports.HTTP_HEADER = exports.ERR_SC = void 0;
19
+ exports.events = exports.wsEventChannel = exports.archiveRoot = exports.archiveObj = exports.cancelRootTransaction = exports.cancelTransaction = exports.addDiffSectionTo = exports.sanitizedDiff = exports.archivedRootVersion = exports.archivedObjVersion = exports.currentRootObj = exports.currentObj = exports.keyDerivParams = exports.PARAM_SC = exports.sessionParams = exports.closeSession = exports.midLogin = exports.BIN_TYPE = exports.HTTP_HEADER = exports.ERR_SC = void 0;
20
20
  /**
21
21
  * This defines interfaces for 3nstorage owner's requests.
22
22
  */
@@ -123,32 +123,22 @@ Object.freeze(currentRootObj);
123
123
  var archivedObjVersion;
124
124
  (function (archivedObjVersion) {
125
125
  archivedObjVersion.EXPRESS_URL_END = '/obj/:objId/archived';
126
- function getReqUrlEnd(objId, version, opts) {
127
- if (opts) {
128
- opts.ver = version;
129
- }
130
- const query = (opts ? `?${(0, querystring_1.stringify)(opts)}` : '');
131
- return `/obj/${objId}/archived${query}`;
126
+ function getReqUrlEnd(objId, opts) {
127
+ return `/obj/${objId}/archived?${(0, querystring_1.stringify)(opts)}`;
132
128
  }
133
129
  archivedObjVersion.getReqUrlEnd = getReqUrlEnd;
134
130
  archivedObjVersion.SC = {
135
131
  okGet: 200,
136
- okDelete: 200,
137
- missing: 474,
138
- concurrentTransaction: 483,
139
- incompatibleObjState: 484
132
+ unknownObj: 474,
133
+ unknownObjVer: 494
140
134
  };
141
135
  })(archivedObjVersion = exports.archivedObjVersion || (exports.archivedObjVersion = {}));
142
136
  Object.freeze(archivedObjVersion);
143
137
  var archivedRootVersion;
144
138
  (function (archivedRootVersion) {
145
139
  archivedRootVersion.EXPRESS_URL_END = 'root/archived';
146
- function getReqUrlEnd(version, opts) {
147
- if (opts) {
148
- opts.ver = version;
149
- }
150
- const query = (opts ? `?${(0, querystring_1.stringify)(opts)}` : '');
151
- return `root/archived${query}`;
140
+ function getReqUrlEnd(opts) {
141
+ return `root/archived?${(0, querystring_1.stringify)(opts)}`;
152
142
  }
153
143
  archivedRootVersion.getReqUrlEnd = getReqUrlEnd;
154
144
  archivedRootVersion.SC = archivedObjVersion.SC;
@@ -237,16 +227,30 @@ var archiveObj;
237
227
  return `obj/${objId}/archive`;
238
228
  }
239
229
  archiveObj.getReqUrlEnd = getReqUrlEnd;
230
+ function postAndDelReqUrlEnd(objId, version) {
231
+ return `obj/${objId}/archive?ver=${version}`;
232
+ }
233
+ archiveObj.postAndDelReqUrlEnd = postAndDelReqUrlEnd;
240
234
  archiveObj.SC = {
241
235
  okGet: 200,
242
- okPut: 201,
243
- missing: 474
236
+ okPost: 200,
237
+ okDelete: 200,
238
+ unknownObj: 474,
239
+ unknownObjVer: 494
244
240
  };
245
241
  })(archiveObj = exports.archiveObj || (exports.archiveObj = {}));
246
242
  Object.freeze(archiveObj);
247
243
  var archiveRoot;
248
244
  (function (archiveRoot) {
249
245
  archiveRoot.URL_END = 'root/archive';
246
+ function getReqUrlEnd() {
247
+ return `root/archive`;
248
+ }
249
+ archiveRoot.getReqUrlEnd = getReqUrlEnd;
250
+ function postAndDelReqUrlEnd(version) {
251
+ return `root/archive?ver=${version}`;
252
+ }
253
+ archiveRoot.postAndDelReqUrlEnd = postAndDelReqUrlEnd;
250
254
  archiveRoot.SC = archiveObj.SC;
251
255
  })(archiveRoot = exports.archiveRoot || (exports.archiveRoot = {}));
252
256
  Object.freeze(archiveRoot);
@@ -259,14 +263,34 @@ var wsEventChannel;
259
263
  Object.freeze(wsEventChannel.SC);
260
264
  })(wsEventChannel = exports.wsEventChannel || (exports.wsEventChannel = {}));
261
265
  Object.freeze(wsEventChannel);
262
- var objChanged;
263
- (function (objChanged) {
264
- objChanged.EVENT_NAME = 'obj-changed';
265
- })(objChanged = exports.objChanged || (exports.objChanged = {}));
266
- Object.freeze(objChanged);
267
- var objRemoved;
268
- (function (objRemoved) {
269
- objRemoved.EVENT_NAME = 'obj-removed';
270
- })(objRemoved = exports.objRemoved || (exports.objRemoved = {}));
271
- Object.freeze(objChanged);
266
+ var events;
267
+ (function (events) {
268
+ let objChanged;
269
+ (function (objChanged) {
270
+ objChanged.EVENT_NAME = 'obj-changed';
271
+ })(objChanged = events.objChanged || (events.objChanged = {}));
272
+ Object.freeze(objChanged);
273
+ let objRemoved;
274
+ (function (objRemoved) {
275
+ objRemoved.EVENT_NAME = 'obj-removed';
276
+ })(objRemoved = events.objRemoved || (events.objRemoved = {}));
277
+ Object.freeze(objRemoved);
278
+ let objVersionArchived;
279
+ (function (objVersionArchived) {
280
+ objVersionArchived.EVENT_NAME = 'obj-ver-archived';
281
+ })(objVersionArchived = events.objVersionArchived || (events.objVersionArchived = {}));
282
+ Object.freeze(objVersionArchived);
283
+ let objArchivedVersionRemoved;
284
+ (function (objArchivedVersionRemoved) {
285
+ objArchivedVersionRemoved.EVENT_NAME = 'obj-ver-removed';
286
+ })(objArchivedVersionRemoved = events.objArchivedVersionRemoved || (events.objArchivedVersionRemoved = {}));
287
+ Object.freeze(objArchivedVersionRemoved);
288
+ events.all = [
289
+ objChanged.EVENT_NAME,
290
+ objRemoved.EVENT_NAME,
291
+ objVersionArchived.EVENT_NAME,
292
+ objArchivedVersionRemoved.EVENT_NAME,
293
+ ];
294
+ })(events = exports.events || (exports.events = {}));
295
+ Object.freeze(events);
272
296
  Object.freeze(exports);
@@ -1,4 +1,5 @@
1
1
  /// <reference types="node" />
2
+ /// <reference types="node" />
2
3
  import * as http from 'http';
3
4
  import * as https from 'https';
4
5
  import * as express from 'express';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spec-3nweb-server",
3
- "version": "1.4.1",
3
+ "version": "1.5.2",
4
4
  "description": "3NWeb spec server.",
5
5
  "main": "build/lib.js",
6
6
  "types": "build/lib.d.ts",
@@ -36,13 +36,13 @@
36
36
  "xsp-files": "^2.0.0"
37
37
  },
38
38
  "devDependencies": {
39
- "@types/express": "",
40
- "@types/jasmine": "",
41
- "@types/node": "",
39
+ "@types/express": "4.17.13",
40
+ "@types/jasmine": "^3.9.1",
41
+ "@types/node": "^16.11.7",
42
42
  "@types/ws": "^4.0.0",
43
- "jasmine": "^2.5.3",
43
+ "jasmine": "^3.9.0",
44
44
  "rxjs": "^5.3.0",
45
- "typescript": "^4.6.3",
45
+ "typescript": "^4.7.4",
46
46
  "xhr2": "^0.1.3"
47
47
  },
48
48
  "readmeFilename": "README.md"