@researchdatabox/sails-hook-redbox-storage-mongo 1.4.9 → 1.5.1

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.
@@ -0,0 +1,12 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ target-branch: "master"
8
+ - package-ecosystem: "npm"
9
+ directory: "/"
10
+ schedule:
11
+ interval: "weekly"
12
+ target-branch: "master"
package/README.md CHANGED
File without changes
File without changes
File without changes
File without changes
@@ -12,8 +12,9 @@ var __await = (this && this.__await) || function (v) { return this instanceof __
12
12
  var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
13
13
  if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
14
14
  var g = generator.apply(thisArg, _arguments || []), i, q = [];
15
- return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
16
- function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
15
+ return i = {}, verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
16
+ function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
17
+ function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
17
18
  function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
18
19
  function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
19
20
  function fulfill(value) { resume("next", value); }
@@ -22,9 +23,9 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar
22
23
  };
23
24
  Object.defineProperty(exports, "__esModule", { value: true });
24
25
  exports.Services = void 0;
25
- const Rx_1 = require("rxjs/Rx");
26
+ const rxjs_1 = require("rxjs");
26
27
  const uuid_1 = require("uuid");
27
- const moment = require("moment");
28
+ const luxon_1 = require("luxon");
28
29
  const mongodb = require("mongodb");
29
30
  const util = require("util");
30
31
  const stream = require("stream");
@@ -151,8 +152,14 @@ var Services;
151
152
  response.success = true;
152
153
  }
153
154
  catch (err) {
154
- sails.log.error(`${this.logHeader} Failed to save update to MongoDB:`);
155
- sails.log.error(JSON.stringify(err));
155
+ sails.log.error(`${this.logHeader} Failed to save update to MongoDB: ${JSON.stringify({
156
+ error: err,
157
+ response: response,
158
+ brand: brand,
159
+ oid: oid,
160
+ record: record,
161
+ user: user,
162
+ })}`);
156
163
  response.success = false;
157
164
  response.message = err;
158
165
  }
@@ -199,28 +206,24 @@ var Services;
199
206
  provideUserAccessAndRemovePendingAccess(oid, userid, pendingValue) {
200
207
  const batchFn = () => __awaiter(this, void 0, void 0, function* () {
201
208
  const metadata = yield this.getMeta(oid);
202
- var pendingEditArray = metadata['authorization']['editPending'];
203
- var editArray = metadata['authorization']['edit'];
204
- for (var i = 0; i < pendingEditArray.length; i++) {
205
- if (pendingEditArray[i] == pendingValue) {
206
- pendingEditArray = pendingEditArray.filter(e => e !== pendingValue);
207
- editArray = editArray.filter(e => e !== userid);
208
- editArray.push(userid);
209
- }
210
- }
211
- metadata['authorization']['editPending'] = pendingEditArray;
212
- metadata['authorization']['edit'] = editArray;
213
- var pendingViewArray = metadata['authorization']['viewPending'];
214
- var viewArray = metadata['authorization']['view'];
215
- for (var i = 0; i < pendingViewArray.length; i++) {
216
- if (pendingViewArray[i] == pendingValue) {
217
- pendingViewArray = pendingViewArray.filter(e => e !== pendingValue);
218
- viewArray = viewArray.filter(e => e !== userid);
219
- viewArray.push(userid);
220
- }
221
- }
222
- metadata['authorization']['viewPending'] = pendingViewArray;
223
- metadata['authorization']['view'] = viewArray;
209
+ const pendingEditArray = _.get(metadata, 'authorization.editPending', []);
210
+ const editArray = _.get(metadata, 'authorization.edit', []);
211
+ const pendingEditArrayFiltered = pendingEditArray.filter(value => value !== pendingValue);
212
+ const pendingEditFound = pendingEditArray.length > pendingEditArrayFiltered.length;
213
+ if (pendingEditFound && !editArray.includes(userid)) {
214
+ editArray.push(userid);
215
+ }
216
+ _.set(metadata, 'authorization.editPending', pendingEditArrayFiltered);
217
+ _.set(metadata, 'authorization.edit', editArray);
218
+ const pendingViewArray = _.get(metadata, 'authorization.viewPending', []);
219
+ const viewArray = _.get(metadata, 'authorization.view', []);
220
+ const pendingViewArrayFiltered = pendingViewArray.filter(value => value !== pendingValue);
221
+ const pendingViewFound = pendingViewArray.length > pendingViewArrayFiltered.length;
222
+ if (pendingViewFound && !viewArray.includes(userid)) {
223
+ viewArray.push(userid);
224
+ }
225
+ _.set(metadata, 'authorization.viewPending', pendingViewArrayFiltered);
226
+ _.set(metadata, 'authorization.view', viewArray);
224
227
  try {
225
228
  yield this.updateMeta(null, oid, metadata);
226
229
  }
@@ -231,8 +234,8 @@ var Services;
231
234
  });
232
235
  batchFn();
233
236
  }
234
- getRelatedRecords(oid, brand, recordTypeName = null, mappingContext = null) {
235
- return __awaiter(this, void 0, void 0, function* () {
237
+ getRelatedRecords(oid_1, brand_1) {
238
+ return __awaiter(this, arguments, void 0, function* (oid, brand, recordTypeName = null, mappingContext = null) {
236
239
  let record = yield this.getMeta(oid);
237
240
  if (_.isEmpty(recordTypeName)) {
238
241
  recordTypeName = record['metaMetadata']['type'];
@@ -284,8 +287,8 @@ var Services;
284
287
  return mappingContext;
285
288
  });
286
289
  }
287
- delete(oid, permanentlyDelete = false) {
288
- return __awaiter(this, void 0, void 0, function* () {
290
+ delete(oid_1) {
291
+ return __awaiter(this, arguments, void 0, function* (oid, permanentlyDelete = false) {
289
292
  const response = new redbox_core_types_1.StorageServiceResponse();
290
293
  try {
291
294
  if (permanentlyDelete) {
@@ -333,7 +336,7 @@ var Services;
333
336
  const logName = _.get(options, 'logName', null);
334
337
  if (logName) {
335
338
  let log = _.get(record, logName, null);
336
- const entry = { date: moment().format('YYYY-MM-DDTHH:mm:ss') };
339
+ const entry = { date: luxon_1.DateTime.now().toFormat("yyyy-LL-dd'T'HH:mm:ss") };
337
340
  if (log) {
338
341
  log.push(entry);
339
342
  }
@@ -367,8 +370,8 @@ var Services;
367
370
  return record;
368
371
  });
369
372
  }
370
- getDeletedRecords(workflowState, recordType = undefined, start, rows = 10, username, roles, brand, editAccessOnly = undefined, packageType = undefined, sort = undefined, filterFields = undefined, filterString = undefined, filterMode = 'regex') {
371
- return __awaiter(this, void 0, void 0, function* () {
373
+ getDeletedRecords(workflowState_1) {
374
+ return __awaiter(this, arguments, void 0, function* (workflowState, recordType = undefined, start, rows = 10, username, roles, brand, editAccessOnly = undefined, packageType = undefined, sort = undefined, filterFields = undefined, filterString = undefined, filterMode = 'regex') {
372
375
  let query = {
373
376
  "deletedRecordMetadata.metaMetadata.brandId": brand.id
374
377
  };
@@ -446,8 +449,8 @@ var Services;
446
449
  return response;
447
450
  });
448
451
  }
449
- getRecords(workflowState, recordType = undefined, start, rows = 10, username, roles, brand, editAccessOnly = undefined, packageType = undefined, sort = undefined, filterFields = undefined, filterString = undefined, filterMode = undefined, secondarySort = undefined) {
450
- return __awaiter(this, void 0, void 0, function* () {
452
+ getRecords(workflowState_1) {
453
+ return __awaiter(this, arguments, void 0, function* (workflowState, recordType = undefined, start, rows = 10, username, roles, brand, editAccessOnly = undefined, packageType = undefined, sort = undefined, filterFields = undefined, filterString = undefined, filterMode = undefined, secondarySort = undefined) {
451
454
  if (_.isUndefined(filterMode) || _.isNull(filterMode) || _.isEmpty(filterMode)) {
452
455
  filterMode = 'regex';
453
456
  }
@@ -563,8 +566,8 @@ var Services;
563
566
  return { items: yield this.deletedRecordCol.find(query, options).toArray(), totalItems: yield this.deletedRecordCol.count(query) };
564
567
  });
565
568
  }
566
- fetchAllRecords(query, options, stringifyJSON = false) {
567
- return __asyncGenerator(this, arguments, function* fetchAllRecords_1() {
569
+ fetchAllRecords(query_1, options_1) {
570
+ return __asyncGenerator(this, arguments, function* fetchAllRecords_1(query, options, stringifyJSON = false) {
568
571
  let skip = 0;
569
572
  let limit = options.limit;
570
573
  options.skip = skip;
@@ -689,9 +692,9 @@ var Services;
689
692
  reqs.push(this.addAndRemoveDatastreams(oid, fileIdsAdded, removeIds));
690
693
  }));
691
694
  if (_.isEmpty(reqs)) {
692
- reqs.push(Rx_1.Observable.of({ "request": "dummy" }));
695
+ reqs.push((0, rxjs_1.of)({ "request": "dummy" }));
693
696
  }
694
- return Rx_1.Observable.of(reqs);
697
+ return (0, rxjs_1.of)(reqs);
695
698
  });
696
699
  }
697
700
  removeDatastream(oid, datastream) {
package/config/record.js CHANGED
File without changes
package/config/storage.js CHANGED
File without changes
package/index.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@researchdatabox/sails-hook-redbox-storage-mongo",
3
- "version": "1.4.9",
3
+ "version": "1.5.1",
4
4
  "description": "A MongoDB storage plugin for ReDBox.",
5
5
  "main": "index.js",
6
6
  "sails": {
@@ -11,9 +11,16 @@
11
11
  "url": "https://github.com/redbox-mint/sails-hook-redbox-storage-mongo.git"
12
12
  },
13
13
  "scripts": {
14
- "test": "NODE_ENV=test; mocha",
15
- "installHook": "docker run -v $(pwd):/opt/sailshook qcifengineering/redbox-portal /bin/bash -c 'cd /opt/redbox-portal;yarn add \"file:/opt/sailshook\"'; docker commit $(docker ps -lq) redboxportalwithhook",
16
- "runDev": "docker-compose -f support/development/docker-compose.yml up"
14
+ "compile": "./node_modules/typescript/bin/tsc -p tsconfig.json",
15
+ "dev:run": "docker compose -f ./support/docker-compose.yml -f ./support/docker-compose.dev.yml up --menu=false --remove-orphans --abort-on-container-exit --exit-code-from rbportal",
16
+ "predev:run": "npm install --ignore-scripts && npm run compile",
17
+ "dev:clean": "docker compose -f ./support/docker-compose.yml -f ./support/docker-compose.dev.yml down",
18
+ "dev:logs": "docker compose -f ./support/docker-compose.yml -f ./support/docker-compose.dev.yml logs",
19
+ "dev:removedata": "docker compose -f ./support/docker-compose.yml -f ./support/docker-compose.dev.yml down -v",
20
+ "test": "docker compose -f ./support/docker-compose.yml -f ./support/docker-compose.mocha.yml up --menu=false --abort-on-container-exit --exit-code-from rbportal",
21
+ "pretest": "npm install --ignore-scripts && npm run compile",
22
+ "posttest": "npm run test:clean",
23
+ "test:clean": "docker compose -f ./support/docker-compose.yml -f ./support/docker-compose.mocha.yml down -v"
17
24
  },
18
25
  "keywords": [
19
26
  "sails",
@@ -26,27 +33,31 @@
26
33
  "author": "QCIF Engineering dev@redboxresearchdata.com.au",
27
34
  "license": "GPL-3.0",
28
35
  "devDependencies": {
29
- "@researchdatabox/redbox-core-types": "^1.4.3",
30
- "@types/chai": "^4.2.12",
31
- "@types/lodash": "^4.14.159",
32
- "@types/mocha": "^8.0.3",
33
- "chai": "^4.2.0",
36
+ "@researchdatabox/redbox-core-types": "^1.5.0",
37
+ "@types/chai": "5.2.2",
38
+ "@types/lodash": "4.17.17",
39
+ "@types/mocha": "10.0.10",
40
+ "@types/node": "20.17.51",
41
+ "chai": "5.2.0",
34
42
  "fs": "0.0.1-security",
35
- "mocha": "^8.1.1",
36
- "moment": "^2.29.1",
37
- "mongodb": "^6.2.0",
38
- "rxjs": "^6.6.2",
39
- "rxjs-compat": "^6.6.7",
40
- "sails": "^1.2.5",
41
- "stream": "0.0.2",
42
- "typescript": "^5.2.2",
43
- "util": "^0.12.4"
43
+ "luxon": "^3.7.1",
44
+ "mocha": "11.5.0",
45
+ "mocha-junit-reporter": "2.2.1",
46
+ "mongodb": "6.16.0",
47
+ "sails": "1.5.14",
48
+ "stream": "0.0.3",
49
+ "typescript": "5.5.4",
50
+ "util": "0.12.5"
44
51
  },
45
52
  "dependencies": {
46
53
  "json2csv": "^5.0.3",
47
54
  "lodash": "^4.17.21",
48
55
  "uuid": "8.3.0"
49
56
  },
57
+ "peerDependencies": {
58
+ "luxon": ">=3.0.0",
59
+ "rxjs": ">=7.0.0"
60
+ },
50
61
  "publishConfig": {
51
62
  "access": "public"
52
63
  }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ module.exports = {
4
+ require: "chai",
5
+ recursive: true,
6
+ slow: 2000,
7
+ timeout: "20s",
8
+ ui: "bdd",
9
+ global: ["sails", "moment", "_", "expect"],
10
+ };
11
+
12
+ if (process.env.CI === "true") {
13
+ console.log("Mocha running in CI.");
14
+ // (For CI) Run mocha and write results to a junit format file:
15
+ module.exports["reporter"] = "mocha-junit-reporter";
16
+ module.exports["reporter-option"] = "mochaFile=/opt/redbox-portal/node_modules/@researchdatabox/sails-hook-redbox-storage-mongo/support/junit/unit-mocha.xml";
17
+ } else {
18
+ console.log("Mocha running in local dev.");
19
+ // (For development) Run mocha and show the results on stdout:
20
+ module.exports["reporter"] = "spec";
21
+ }
@@ -0,0 +1,63 @@
1
+ var sails = require("sails");
2
+ var _ = require("lodash");
3
+
4
+ global.moment = require("moment");
5
+ global.sails = sails;
6
+ global._ = _;
7
+
8
+ /* global before, after */
9
+
10
+ before(function (done) {
11
+ import("chai").then((chai) => {
12
+ global.chai = chai;
13
+ global.should = chai.should();
14
+ global.expect = chai.expect;
15
+
16
+ // Set the timeout so that Sails has enough time to lift.
17
+ this.timeout(60000);
18
+ sails.lift({
19
+ log: {
20
+ level: "verbose",
21
+ },
22
+ hooks: {
23
+ grunt: false,
24
+ },
25
+ models: {
26
+ datastore: "mongodb",
27
+ migrate: "drop",
28
+ },
29
+ datastores: {
30
+ mongodb: {
31
+ adapter: require('sails-mongo'),
32
+ url: "mongodb://mongodb:27017/redbox-portal"
33
+ },
34
+ redboxStorage: {
35
+ adapter: require('sails-mongo'),
36
+ url: 'mongodb://mongodb:27017/redbox-storage'
37
+ }
38
+ },
39
+ security: {
40
+ csrf: false,
41
+ },
42
+ auth: {
43
+ default: {
44
+ local: {
45
+ default: {
46
+ token: "auth-default-local-default-token",
47
+ },
48
+ },
49
+ },
50
+ },
51
+ }, function (err, server) {
52
+ if (err) return done(err);
53
+ done(err, sails);
54
+ });
55
+ });
56
+ });
57
+
58
+ after(function (done) {
59
+ // here you can clear fixtures, etc.
60
+ if (sails && _.isFunction(sails.lower)) {
61
+ sails.lower(done);
62
+ }
63
+ });
@@ -0,0 +1,121 @@
1
+ const service = require("../../../api/services/MongoStorageService");
2
+
3
+
4
+ /* global describe, it, expect */
5
+
6
+ async function sleep(ms = 300) {
7
+ return new Promise(resolve => setTimeout(resolve, ms));
8
+ }
9
+
10
+ describe("Records", function () {
11
+ [
12
+ {
13
+ // missing 'editPending' does not cause error
14
+ args: {
15
+ record: {
16
+ metadata: {},
17
+ "authorization": {
18
+ "viewRoles": ["Admin", "Librarians"],
19
+ "editRoles": ["Admin", "Librarians"],
20
+ "view": ["example-2@redboxresearchdata.com.au"],
21
+ "edit": [],
22
+ "viewPending": ["example-1@redboxresearchdata.com.au"]
23
+ }
24
+ }
25
+ },
26
+ expected: {
27
+ record: {
28
+ "authorization": {
29
+ "viewRoles": ["Admin", "Librarians"],
30
+ "editRoles": ["Admin", "Librarians"],
31
+ "view": ["example-2@redboxresearchdata.com.au", "example-1@redboxresearchdata.com.au"],
32
+ "edit": [],
33
+ "viewPending": [],
34
+ "editPending": [],
35
+ }
36
+ }
37
+ },
38
+ },
39
+ {
40
+ // duplicate entries in pending array are transformed to in one entry in real access array
41
+ args: {
42
+ record: {
43
+ metadata: {},
44
+ "authorization": {
45
+ "viewRoles": ["Admin", "Librarians"],
46
+ "editRoles": ["Admin", "Librarians"],
47
+ "view": ["example-2@redboxresearchdata.com.au"],
48
+ "edit": [],
49
+ "viewPending": [],
50
+ "editPending": ["example-1@redboxresearchdata.com.au", "example-1@redboxresearchdata.com.au"],
51
+ }
52
+ }
53
+ },
54
+ expected: {
55
+ record: {
56
+ "authorization": {
57
+ "viewRoles": ["Admin", "Librarians"],
58
+ "editRoles": ["Admin", "Librarians"],
59
+ "view": ["example-2@redboxresearchdata.com.au"],
60
+ "edit": ["example-1@redboxresearchdata.com.au"],
61
+ "viewPending": [],
62
+ "editPending": [],
63
+ }
64
+ }
65
+ },
66
+ },
67
+ {
68
+ // same entry in real access array and pending is removed from pending array
69
+ args: {
70
+ record: {
71
+ metadata: {},
72
+ "authorization": {
73
+ "viewRoles": ["Admin", "Librarians"],
74
+ "editRoles": ["Admin", "Librarians"],
75
+ "view": ["example-2@redboxresearchdata.com.au"],
76
+ "edit": ["example-1@redboxresearchdata.com.au"],
77
+ "viewPending": [],
78
+ "editPending": ["example-1@redboxresearchdata.com.au"],
79
+ }
80
+ }
81
+ },
82
+ expected: {
83
+ record: {
84
+ "authorization": {
85
+ "viewRoles": ["Admin", "Librarians"],
86
+ "editRoles": ["Admin", "Librarians"],
87
+ "view": ["example-2@redboxresearchdata.com.au"],
88
+ "edit": ["example-1@redboxresearchdata.com.au"],
89
+ "viewPending": [],
90
+ "editPending": [],
91
+ }
92
+ }
93
+ },
94
+ }
95
+ ].forEach(({args, expected}) => {
96
+ it(`should provideUserAccessAndRemovePendingAccess as expected '${JSON.stringify(args)}' = ${JSON.stringify(expected)}`, async function () {
97
+
98
+ const brand = 'testing-brand';
99
+ const record = args.record;
100
+ const recordType = "rdmp";
101
+
102
+ const response = await service.create(brand, record, recordType);
103
+
104
+ expect(response.oid).to.have.lengthOf(32);
105
+
106
+ const oid = response.oid;
107
+ const userid = "example-1@redboxresearchdata.com.au";
108
+ const pendingValue = "example-1@redboxresearchdata.com.au";
109
+
110
+ service.provideUserAccessAndRemovePendingAccess(oid, userid, pendingValue);
111
+ // TODO: provideUserAccessAndRemovePendingAccess is a sync method, but it calls async methods.
112
+ // So, wait for a bit for the method to complete.
113
+ // This means that any errors may not be raised, as they occur in an untracked async function.
114
+ await sleep(5000);
115
+
116
+ const result = await service.getMeta(oid);
117
+
118
+ expect(result.authorization).to.eql(expected.record.authorization);
119
+ });
120
+ });
121
+ });
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const { Transform } = require('stream');
4
- const moment = require("moment");
4
+ const luxon_1 = require("luxon");
5
5
  class ExportJSONTransformer extends Transform {
6
6
  constructor(recordtype, modifiedBefore, modifiedAfter) {
7
7
  super();
8
8
  this.first = true;
9
- this.push(`{ "recordType": "${recordtype}",\n "dateGenerated": "${moment().toISOString()}",\n`);
9
+ this.push(`{ "recordType": "${recordtype}",\n "dateGenerated": "${luxon_1.DateTime.now().toISO()}",\n`);
10
10
  if (!_.isEmpty(modifiedBefore) || !_.isEmpty(modifiedAfter)) {
11
11
  this.push(`"dateModifiedRange": ${this.getDateModifiedRangeObject(modifiedBefore, modifiedAfter)},\n`);
12
12
  }
package/tsconfig.json CHANGED
File without changes
@@ -1,10 +1,8 @@
1
- import {
2
- Observable
3
- } from 'rxjs/Rx';
1
+ import { Observable, of } from 'rxjs';
4
2
 
5
3
  import { Sails, Model } from "sails";
6
4
  import { v1 as uuidv1 } from 'uuid';
7
- import moment = require('moment');
5
+ import { DateTime } from 'luxon';
8
6
 
9
7
  import mongodb = require('mongodb');
10
8
  import util = require('util');
@@ -162,8 +160,14 @@ export module Services {
162
160
  await Record.updateOne({ redboxOid: oid }).set(record);
163
161
  response.success = true;
164
162
  } catch (err) {
165
- sails.log.error(`${this.logHeader} Failed to save update to MongoDB:`);
166
- sails.log.error(JSON.stringify(err));
163
+ sails.log.error(`${this.logHeader} Failed to save update to MongoDB: ${JSON.stringify({
164
+ error: err,
165
+ response: response,
166
+ brand: brand,
167
+ oid: oid,
168
+ record: record,
169
+ user: user,
170
+ })}`);
167
171
  response.success = false;
168
172
  response.message = err;
169
173
  }
@@ -208,33 +212,55 @@ export module Services {
208
212
  return response;
209
213
  }
210
214
 
215
+ /**
216
+ * If pendingValue is in editPending or viewPending, remove all instances from the pending arrays and
217
+ * put the userid in the matching access / non-pending array, then save the changes to the storage.
218
+ *
219
+ * Implementation Note: This is a sync method, but it calls async methods.
220
+ * This means that the storage will not be updated when this method returns, but at some point later.
221
+ *
222
+ * @param oid The record identifier.
223
+ * @param userid The value to put in the matching access / non-pending arrays.
224
+ * @param pendingValue The value to find in the pending arrays.
225
+ */
211
226
  public provideUserAccessAndRemovePendingAccess(oid, userid, pendingValue): void {
212
227
  const batchFn = async () => {
213
228
  const metadata = await this.getMeta(oid);
214
- // remove pending edit access and add real edit access with userid
215
- var pendingEditArray = metadata['authorization']['editPending'];
216
- var editArray = metadata['authorization']['edit'];
217
- for (var i = 0; i < pendingEditArray.length; i++) {
218
- if (pendingEditArray[i] == pendingValue) {
219
- pendingEditArray = pendingEditArray.filter(e => e !== pendingValue);
220
- editArray = editArray.filter(e => e !== userid);
221
- editArray.push(userid);
222
- }
229
+
230
+ // Update edit authorization - remove pending edit access and add real edit access with userid
231
+ const pendingEditArray: string[] = _.get(metadata, 'authorization.editPending', []);
232
+ const editArray: string[] = _.get(metadata, 'authorization.edit', []);
233
+
234
+ // remove all items matching pendingValue from the pendingEditArray
235
+ const pendingEditArrayFiltered = pendingEditArray.filter(value => value !== pendingValue);
236
+ const pendingEditFound = pendingEditArray.length > pendingEditArrayFiltered.length;
237
+
238
+ // add the item to the editArray if it existed in the pendingEditArray, and it is not in the editArray
239
+ if (pendingEditFound && !editArray.includes(userid)) {
240
+ editArray.push(userid);
223
241
  }
224
- metadata['authorization']['editPending'] = pendingEditArray;
225
- metadata['authorization']['edit'] = editArray;
226
-
227
- var pendingViewArray = metadata['authorization']['viewPending'];
228
- var viewArray = metadata['authorization']['view'];
229
- for (var i = 0; i < pendingViewArray.length; i++) {
230
- if (pendingViewArray[i] == pendingValue) {
231
- pendingViewArray = pendingViewArray.filter(e => e !== pendingValue);
232
- viewArray = viewArray.filter(e => e !== userid);
233
- viewArray.push(userid);
234
- }
242
+
243
+ // update the metadata with the modified arrays
244
+ _.set(metadata, 'authorization.editPending', pendingEditArrayFiltered);
245
+ _.set(metadata, 'authorization.edit', editArray);
246
+
247
+ // Update view authorization - remove pending view access and add real view access with userid
248
+ const pendingViewArray: string[] = _.get(metadata, 'authorization.viewPending', []);
249
+ const viewArray: string[] = _.get(metadata, 'authorization.view', []);
250
+
251
+ // remove all items matching pendingValue from the pendingViewArray
252
+ const pendingViewArrayFiltered = pendingViewArray.filter(value => value !== pendingValue);
253
+ const pendingViewFound = pendingViewArray.length > pendingViewArrayFiltered.length;
254
+
255
+ // add the item to the viewArray if it existed in the pendingViewArray, and it is not in the viewArray
256
+ if (pendingViewFound && !viewArray.includes(userid)) {
257
+ viewArray.push(userid);
235
258
  }
236
- metadata['authorization']['viewPending'] = pendingViewArray;
237
- metadata['authorization']['view'] = viewArray;
259
+
260
+ // update the metadata with the modified arrays
261
+ _.set(metadata, 'authorization.viewPending', pendingViewArrayFiltered);
262
+ _.set(metadata, 'authorization.view', viewArray);
263
+
238
264
  try {
239
265
  await this.updateMeta(null, oid, metadata);
240
266
  } catch (err) {
@@ -242,6 +268,8 @@ export module Services {
242
268
  sails.log.error(JSON.stringify(err));
243
269
  }
244
270
  };
271
+
272
+ // TODO: Fix this so that the method only returns after the storage is updated.
245
273
  batchFn();
246
274
  }
247
275
 
@@ -345,7 +373,8 @@ export module Services {
345
373
  const logName = _.get(options, 'logName', null);
346
374
  if (logName) {
347
375
  let log = _.get(record, logName, null);
348
- const entry = { date: moment().format('YYYY-MM-DDTHH:mm:ss') };
376
+ // Use Luxon for ISO-like local timestamp without timezone offset
377
+ const entry = { date: DateTime.now().toFormat("yyyy-LL-dd'T'HH:mm:ss") };
349
378
  if (log) {
350
379
  log.push(entry);
351
380
  } else {
@@ -733,9 +762,9 @@ export module Services {
733
762
  reqs.push(this.addAndRemoveDatastreams(oid, fileIdsAdded, removeIds));
734
763
  });
735
764
  if (_.isEmpty(reqs)) {
736
- reqs.push(Observable.of({ "request": "dummy" }));
765
+ reqs.push(of({ "request": "dummy" }));
737
766
  }
738
- return Observable.of(reqs);
767
+ return of(reqs);
739
768
  });
740
769
  }
741
770
 
@@ -1,16 +1,16 @@
1
1
  'use strict';
2
2
 
3
- const {
4
- Transform
5
- } = require('stream');
6
- import moment = require('moment');
3
+ const { Transform } = require('stream');
4
+ import { DateTime } from 'luxon';
5
+ declare var require: any;
6
+ declare var module: any;
7
7
  declare let sails, _;
8
8
 
9
9
  class ExportJSONTransformer extends Transform {
10
10
  first:boolean = true;
11
11
  constructor(recordtype:string, modifiedBefore:string, modifiedAfter:string) {
12
12
  super();
13
- this.push(`{ "recordType": "${recordtype}",\n "dateGenerated": "${moment().toISOString()}",\n`)
13
+ this.push(`{ "recordType": "${recordtype}",\n "dateGenerated": "${DateTime.now().toISO()}",\n`)
14
14
  if(!_.isEmpty(modifiedBefore) || !_.isEmpty(modifiedAfter)) {
15
15
  this.push(`"dateModifiedRange": ${this.getDateModifiedRangeObject(modifiedBefore, modifiedAfter)},\n`);
16
16
  }
package/test/bootstrap.js DELETED
@@ -1,65 +0,0 @@
1
- var Sails = require('sails').Sails;
2
-
3
- describe('Bootstrap tests ::', function() {
4
- // Var to hold a running sails app instance
5
- var _sails;
6
- var appPath = '/opt/redbox-portal'
7
-
8
- // Before running any tests, attempt to lift Sails
9
- before(function (done) {
10
-
11
- // Hook will timeout in 10 seconds
12
- this.timeout(11000);
13
-
14
- // Attempt to lift sails
15
- Sails().lift({
16
- appPath: appPath,
17
- models: {
18
- migrate: 'drop'
19
- },
20
- datastores: {
21
- mongodb: {
22
- adapter: require(appPath+'/node_modules/sails-mongo'),
23
- url: "mongodb://mongodb:27017/redbox-portal"
24
- },
25
- redboxStorage: {
26
- adapter: require(appPath+'/node_modules/sails-mongo'),
27
- url: 'mongodb://mongodb:27017/redbox-storage'
28
- }
29
- },
30
- globals: {
31
- sails: true,
32
- _: require('lodash'),
33
- async: require('async'),
34
- models: true,
35
- services: true
36
- },
37
- hooks: {
38
- // Skip grunt (unless your hook uses it)
39
- "grunt": false
40
- },
41
- log: {level: "verbose"}
42
- },function (err, __sails) {
43
- if (err) return done(err);
44
- _sails = __sails;
45
- return done();
46
- });
47
- });
48
-
49
- // After tests are complete, lower Sails
50
- after(function (done) {
51
-
52
- // Lower Sails (if it successfully lifted)
53
- if (_sails) {
54
- return _sails.lower(done);
55
- }
56
- // Otherwise just return
57
- return done();
58
- });
59
-
60
- // Test that Sails can lift with the hook in place
61
- it ('sails does not crash', function() {
62
- return true;
63
- });
64
-
65
- });